sparksql的三種join方式

簡介

對於Spark來說有3種Join的實現,每種Join對應的不同的應用場景(SparkSQL自動決策使用哪種實現範式(這句話參考別人博客,需要驗證)):

  1. Broadcast Hash Join適合一張很小的表和一張大表進行Join
  2. Shuffle Hash Join適合一張小表(比上一個大一點)和一張大表進行Join
  3. Sort Merge Join適合兩張大表進行Join

前兩者都是基於Hash Join的,只不過Hash Join之前需要先shuffle還是先brocadcast。

Broadcast Hash Join

條件:

  1. 被廣播的表需要小於spark.sql.autoBroadcastJoinThreshold所配置的信息,默認是10M;
  2. 基表不能被廣播,比如left outer join時,左邊的表就是基表,此時就只能廣播右表。

缺點

這個方案只能用於廣播較小的表,否則數據的冗餘傳輸就遠大於shuffle的開銷;另外,廣播時需要將被廣播的表現collect到driver端,當頻繁有廣播出現時,對driver的內存也是一個考驗。

舉個列子:

數據庫的常見模型中(比如星型模型或者雪花模型),表一般分爲兩種:事實表和維度表
維度表一般指固定的、變動較少的表
事實表一遍記錄流水,比如銷售清單等,通過隨着時間的增長不斷增長

Join操作是對兩個表中key值相同的記錄進行連接
在SparkSQL中,對兩個表做Join最直接的方式是先根據key分區,再在每個分區中把key值相同的記錄拿出來做連接操作
這樣就不可避免地涉及到shuffle,而shuffle在Spark中是比較耗時的操作,我們應該儘可能的設計Spark應用使其避免大量的shuffle。
當維度表和事實表進行Join操作時,爲了避免shuffle,我們可以將大小有限的維度表的全部數據分發到每個節點上,供事實表使用。executor存儲維度表的全部數據,一定程度上犧牲了空間,換取shuffle操作大量的耗時,這在SparkSQL中稱作Broadcast Join
在這裏插入圖片描述
Table B是較小的表,黑色表示將其廣播到每個executor節點上,Table A的每個partition會通過block manager取到Table A的數據。根據每條記錄的Join Key取到Table B中相對應的記錄,根據Join Type進行操作

Shuffle Hash Join

條件

分區的平均大小不超過spark.sql.autoBroadcastJoinThreshold所配置的值,默認是10M
基表不能被廣播,比如left outer join時,只能廣播右表
一側的表要明顯小於另外一側,小的一側將被廣播(明顯小於的定義爲3倍小)

舉例

當一側的表比較小時,我們可以選擇將其廣播出去以避免shuffle,提高性能。但因爲被廣播的表首先被collect到driver端,然後被冗餘的發送給各個executor上,所以當表比較大是,採用broadcast join會對driver端和executor端造成較大的壓力。
可以通過分區的形式將大批量的數據劃分成n份較小的數據集進行並行計算。這種思想應用到Join上便是Shuffle Hash Join了。利用key相同必然分區相同的這個原理,SparkSQL將較大表的join分而治之,先將表劃分成n個分區,再對兩個表中相對應分區的數據分別進行Hash Join,這樣即在一定程度上減少了driver廣播一側表的壓力,也減少了executor端取整張被廣播表的內存消耗。其原理如下圖:
在這裏插入圖片描述
對兩張表分別按照join keys進行重分區,即shuffle,目的是爲了讓有相同join keys值的記錄分到對應的分區中
對對應分區中的數據進行join,此處先將小表分區構造爲一張hash表,然後根據大表分區中記錄的join keys值拿出來進行匹配

Sort Merge Join

上面介紹的兩種實現對於一定大小的表比較適用,但當兩個表都非常大時,顯然無論適用哪種都會對計算內存造成很大壓力。這是因爲join時兩者採取的都是hash join,是將一側的數據完全加載到內存中,使用hash code取join keys值相等的記錄進行連接。
當兩個表都非常大時,SparkSQL採用了一種全新的方案來對錶進行Join,即Sort Merge Join。這種實現方式不用將一側數據全部加載後再進星hash join,但需要在join前將數據排序,如下圖所示:
在這裏插入圖片描述

  1. shuffle階段:將兩張大表根據join key進行重新分區,兩張表數據會分佈到整個集羣,以便分佈式並行處理;
  2. sort階段:對單個分區節點的兩表數據,分別進行排序;
  3. merge階段:對排好序的兩張分區表數據執行join操作。join操作很簡單,分別遍歷兩個有序序列,碰到相同join key就merge輸出,否則取更小一邊
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章