Spark Join 源碼剖析①

一、Join 邏輯計劃生成

和 Join 相關的邏輯層的優化規則主要包含以下幾種:

ReorderJoin

EliminateOuterJoin

????DPP 動態分區裁剪

以及

????PushDownPredicates

中和 Join 相關的 predicate pushDown

二、Join 物理計劃生成和選取

2.1、基本概念

在 Spark SQL 中,參與 Join 操作的兩張表分別被稱為流式表(StreamTable)和構件表(BuildTable),不同表的角色在 Spark SQL 中會通過一定的策略進行設定。通常來講,系統會將大表設置為 StreamTable,小表設置為 BuildTable。流式表的迭代器為 streamIter,構建表的迭代器為 buildIter。遍歷 streamIter 的每一條記錄,然后在 buildIter 中查找匹配的記錄。這個查找過程稱為 build 過程。每次 build 操作的結果為一條 JoinedRow(A, B),其中 A 來自 streamedIter,B 來自 buildIter。

再例如,在 BroadcastHashJoin 中需要決定廣播哪個數據表。這里的 BuildSide 可以簡單理解為 “構建的一邊”。

在 Spark 中,BuildSide 作為一個抽象類,包含 BuildLeft 和 BuildRight 兩個子類,一般在構造 Join 的執行算子時,都會傳入一個 BuildSide 的構造參數。在 JoinSelection 中通過 canBuildRightcanBuildLeft 判斷一個 Join 類型能否 “構建” 右表和左表。

2.2、物理計劃選取順序

Join 物理執行計劃的選取在 JoinSelection 中進行,其主要邏輯如下:

如果是一個等值 join(equi-join)且包含 join hint,我們依次查看 join hint:

  1. broadcast hint:如果 join 類型支持,使用 broadcast hash join。如果 left 和 right 都有 broadcast hint,選擇 size 較小的一側(基于統計數據)進行 broadcast
  2. sort merge hint:如果 join keys 是可排序的,使用 sort merge join。
  3. shuffle hash hint:如果 join 類型支持,如果 left 和 right 都設置了 shuffle hash hints,選擇 size 較小的一側作為 build side
  4. shuffle replicate NL hint:如果 join type 為 inner like,使用 cartesian product join(笛卡爾積)

JoinSelection 通過 ExtractEquiJoinKeys 來判斷是否為等值 Join 并提取相關信息:


如果沒有指定 hint 或 hint 不適用,Join 選擇順序如下:

  1. 嘗試選用 broadcast hash join:如果 join 類型支持,且 join 的一側 size 足夠小能夠 broadcast。如果都足夠小,選擇更小的一側進行 broadcast(基于統計數據)
  2. 嘗試選用 shuffle hash join:如果 join 類型支持,且 join 的一側 size 足夠小能夠構建 local hash map,且該側 size 顯著小于另一側,且 spark.sql.join.preferSortMergeJoin 為 false
  3. 嘗試選用 sort merge join:如果 join keys 是可排序的
  4. 嘗試選用笛卡爾積:如果是 inner like join
  5. 嘗試選用 broadcast nested loop join:最后的兜底手段,可能會 OOM,如果這里 OOM 了,也沒辦法了

2.3、等值 Join 情況

注①:

createJoinWithoutHint 如下:

2.4、非等值 Join 情況

三、Join 物理計劃執行

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容