禁用當查詢計劃BroadcastNestedLoopJoin播出

如何禁用當查詢計劃BroadcastNestedLoopJoin播出。

寫的亞當Pavlacka

去年發表在:2022年5月23日

本文闡述了如何禁用廣播當查詢計劃BroadcastNestedLoopJoin在物理的計劃。

你禁用後預計播放停止廣播閾值,通過設置spark.sql.autoBroadcastJoinThreshold1,但是Apache火花試圖與廣播廣播大表和失敗錯誤。

這種行為不是一個錯誤,然而意想不到。我們要回顧的預期行為,並提供一個緩解選擇這個問題。

創建表

首先創建兩個表,一個null值table_withNull和其他沒有null值tblA_NoNull

% sql sql(從範圍(10)選擇id) .write.mode .saveAsTable(“覆蓋”)(“tblA_NoNull”) sql(“從範圍選擇id(50)聯盟選擇零”).write.mode .saveAsTable(“覆蓋”)(“table_withNull”)

試圖禁用廣播

我們試圖禁用廣播通過設置spark.sql.autoBroadcastJoinThreshold查詢,子查詢的條款。

% sql spark.conf.set (“spark.sql。autoBroadcastJoinThreshold”, 1) sql (“select * from table_withNull id而不是(從tblA_NoNull選擇id)”) .explain(真正的)

如果你查看查詢計劃,BroadcastNestedLoopJoin在這種情況下可能是最後撤退。似乎即使試圖禁用廣播。

物理計劃= = = = * (2)BroadcastNestedLoopJoin BuildRight, LeftAnti, ((id # 2482 l = id # 2483 l) | | isnull ((id # 2482 l = id # 2483 l))): - * (2) FileScan鋪違約。table_withnull [id # 2482 l]批處理:真的,DataFilters:[],格式:拚花,地點:InMemoryFileIndex [dbfs: / user /蜂巢/倉庫/ table_withnull], PartitionFilters: [], PushedFilters: [], ReadSchema: struct < id: bigint > + - BroadcastExchange IdentityBroadcastMode, [id = # 2586) + - * (1) FileScan鋪違約。tbla_nonull [id # 2483 l]批處理:真的,DataFilters:[],格式:拚花,地點:InMemoryFileIndex [dbfs: / user /蜂巢/倉庫/ tbla_nonull], PartitionFilters: [], PushedFilters: [], ReadSchema: struct < id: bigint >

如果正在處理的數據是足夠大,這導致廣播錯誤當火花試圖播放表。

重寫查詢使用不存在而不是

你可以通過重寫查詢解決問題不存在而不是

% sql / /可以重寫為一個不存在,這將成為一個普通的加入:sql (“select * from table_withNull不存在(選擇1 tblA_NoNull table_withNull的地方。id = tblA_NoNull.id)”) .explain(真正的)

通過使用不存在,查詢運行SortMergeJoin

= = = =物理計劃SortMergeJoin [id # 2482 l], [id # 2483 l], LeftAnti:——排序(id # 2482 l ASC null第一),假的,0:+ -交換hashpartitioning (id # 2482 l, 200), [id = # 2653]: + - * (1) FileScan鋪違約。table_withnull [id # 2482 l]批處理:真的,DataFilters:[],格式:拚花,地點:InMemoryFileIndex [dbfs: / user /蜂巢/倉庫/ table_withnull], PartitionFilters: [], PushedFilters: [], ReadSchema: struct < id: bigint > + -排序(id # 2483 l ASC null第一),假的,0 + -交換hashpartitioning (id # 2483 l, 200), [id = # 2656) + - *(2)項目[id # 2483 l] + - *(2)過濾器isnotnull (id # 2483 l) + - * (2) FileScan鋪違約。tbla_nonull [id # 2483 l]批處理:真的,DataFilters: [isnotnull (id # 2483 l)],格式:拚花,地點:InMemoryFileIndex [dbfs: / user /蜂巢/倉庫/ tbla_nonull], PartitionFilters: [], PushedFilters: [isnotnull (id)], ReadSchema: struct < id: bigint >

解釋

自動火花並沒有這樣做,因為火花和SQL零處理語義稍有不同。

在SQL中,不是在意味著如果有任何空值不是在值,結果是空的。這就是為什麼它隻能執行BroadcastNestedLoopJoin。所有不是在的值必須是已知的,以確保沒有空值。

例如筆記本電腦

這個筆記本有一個完整的示例,顯示為什麼火花不會自動開關BroadcastNestedLoopJoinSortMergeJoin

檢查BroadcastNestedLoopJoin例如筆記本電腦