Spark難點解析:Join實現原理

Join背景介紹


SQL的所有操作,可以分為簡單操作(如過濾where、限制次數limit等)和聚合操作(groupBy,join等)。

其中,join操作是最復雜、代價最大的操作類型,是大部分業務場景的性能瓶頸所在;所以,今天我們基于SparkSQL,來簡要的聊一下SparkSQL所支持的幾種常見的Join算法以及其適用場景。

首先,我們需要知道數倉中表格的分類:按照是否會經常涉及到Join操作,可以簡單分為低層次表和高層次表

低層次表:直接導入數倉的表,列數少,與其他表存在外鍵依賴,查詢起來經常會用到大量Join算法,查詢效率較低

高層次表:由低層次表加工而來,使用SQL將需要join的表預先合并,形成“寬表”。寬表上查詢不需要大量Join,因此效率較高。但是,相對的是,寬表的數據存在大量冗余,同時生成滯后,查詢不及時。

Join使用的結論


Join常見分類&實現機制


當前SparkSQL支持三種Join算法-shuffle hash join、broadcast hash join以及sort merge join。其中前兩者歸根到底都屬于hash join,只不過在hash join之前需要先shuffle還是先broadcast。所以,首先我們來看一下內核hash join的機制。

Hash Join

先來看一個簡單的SQL:select * from order,item where?item.id?= order.id

參與join的兩張表是item和order,join key分別是item.id以及order.id,假設這個Join采用的是hash join算法,整個過程會經歷三步:

1. 確定Build Table(映射表、小表)以及Probe Table(探查表、大表)。其中Build Table用于構建Hash Table,而Probe會遍歷自身所有key,映射到所生成的Hash Table上去匹配。

2. Build Table構建Hash Table。依次讀取Build Table(item)的數據,對于每一行數據根據join key(item.id)進行hash,hash到對應的Bucket,生成hash table中的一條記錄。數據緩存在內存中,如果內存放不下需要dump到外存。

3. Probe Table探測。依次掃描Probe Table(order)的數據,使用相同的hash函數映射Hash Table中的記錄,映射成功之后再檢查join條件(item.id= order.i_id),如果匹配成功就可以將兩者join在一起。

Hash Join原理圖

兩點補充:

1 hash join的性能。從上面的原理圖可以看出,hash join對兩張表基本只掃描一次,算法效率是o(a+b),比起蠻力的笛卡爾積算法的a*b快了很多數量級。

2 為什么說Build Table要盡量選擇小表呢?從原理上也看到了,構建的Hash Table是需要被頻繁訪問的,所以Hash Table最好能全部加載到內存里,這也決定了hash join只適合至少一個小表join的場景。

看完了hash join的內核,我們來看一下這種單機的算法,在大數據分布式情況下,應該如何去做。目前成熟的有兩套算法:broadcast hash join和shuffler hash join。

Broadcast Hash Join

broadcast hash join是將其中一張小表廣播分發到另一張大表所在的分區節點上,分別并發地與其上的分區記錄進行hash join。broadcast適用于小表很小,可以直接廣播的場景。

在執行上,主要可以分為以下兩步:

1. broadcast階段:將小表廣播分發到大表所在的所有主機。分發方式可以有driver分發,或者采用p2p方式。

2. hash join階段:在每個executor上執行單機版hash join,小表映射,大表試探;

需要注意的是,Spark中對于可以廣播的小表,默認限制是10M以下。(參數是spark.sql.autoBroadcastJoinThreshold

Broadcast Hash Join示意圖

Shuffle Hash Join

當join的一張表很小的時候,使用broadcast hash join,無疑效率最高。但是隨著小表逐漸變大,廣播所需內存、帶寬等資源必然就會太大,所以才會有默認10M的資源限制。

所以,當小表逐漸變大時,就需要采用另一種Hash Join來處理:Shuffle Hash Join。

Shuffle Hash Join按照join key進行分區,根據key相同必然分區相同的原理,將大表join分而治之,劃分為小表的join,充分利用集群資源并行化執行。

在執行上,主要可以分為以下兩步:

1. shuffle階段:分別將兩個表按照join key進行分區,將相同join key的記錄重分布到同一節點,兩張表的數據會被重分布到集群中所有節點。

2. hash join階段:每個分區節點上的數據單獨執行單機hash join算法。

Shuffle Hash Join示意圖

剛才也說過,Hash Join適合至少有一個小表的情況,那如果兩個大表需要Join呢?這時候就需要Sort-Merge Join了。

Sort-Merge Join

SparkSQL對兩張大表join采用了全新的算法-sort-merge join,整個過程分為三個步驟:

1. shuffle階段:將兩張大表根據join key進行重新分區,兩張表數據會分布到整個集群,以便分布式并行處理

2. sort階段:對單個分區節點的兩表數據,分別進行排序

3. merge階段:對排好序的兩張分區表數據執行join操作。join操作很簡單,分別遍歷兩個有序序列,碰到相同join key就merge輸出,否則繼續取更小一邊的key。

Sort-Merge Join示意圖

仔細分析的話會發現,sort-merge join的代價并不比shuffle hash join小,反而是多了很多。那為什么SparkSQL還會在兩張大表的場景下選擇使用sort-merge join算法呢?

這和Spark的shuffle實現有關,目前spark的shuffle實現都適用sort-based shuffle算法,因此在經過shuffle之后partition數據都是按照key排序的。因此理論上可以認為數據經過shuffle之后是不需要sort的,可以直接merge。

結論:如何優化


經過上文的分析,可以明確每種Join算法都有自己的適用場景。在優化的時候,除了要根據業務場景選擇合適的join算法之外,還要注意以下幾點:

1 數據倉庫設計時最好避免大表與大表的join查詢。

2 SparkSQL也可以根據內存資源、帶寬資源適量將參數spark.sql.autoBroadcastJoinThreshold調大,讓更多join實際執行為broadcast hash join。


文集

Spark:理論與實踐

文章

五分鐘大數據:Spark入門

Spark編程快速入門

Spark難點解析:Join實現原理

可視化發現Spark數據傾斜


參考鏈接:

SparkSQL – 有必要坐下來聊聊Join:http://hbasefly.com/2017/03/19/sparksql-basic-join/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,003評論 2 374