中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spark SQL中Not in Subquery為何低效以及如何規避

發布時間:2021-12-17 09:47:58 來源:億速云 閱讀:228 作者:柒染 欄目:大數據

這期內容當中小編將會給大家帶來有關Spark SQL中Not in Subquery為何低效以及如何規避,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

首先看個Not in Subquery的SQL:

// test_partition1 和 test_partition2為Hive外部分區表select * from test_partition1 t1 where t1.id not in (select id from test_partition2);
對應的完整的邏輯計劃和物理計劃為:
== Parsed Logical Plan =='Project [*]+- 'Filter NOT 't1.id IN (list#3 [])   :  +- 'Project ['id]   :     +- 'UnresolvedRelation `test_partition2`   +- 'SubqueryAlias `t1`      +- 'UnresolvedRelation `test_partition1`
== Analyzed Logical Plan ==id: string, name: string, dt: stringProject [id#4, name#5, dt#6]+- Filter NOT id#4 IN (list#3 [])   :  +- Project [id#7]   :     +- SubqueryAlias `default`.`test_partition2`   :        +- HiveTableRelation `default`.`test_partition2`, org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe, [id#7, name#8], [dt#9]   +- SubqueryAlias `t1`      +- SubqueryAlias `default`.`test_partition1`         +- HiveTableRelation `default`.`test_partition1`, org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe, [id#4, name#5], [dt#6]
== Optimized Logical Plan ==Join LeftAnti, ((id#4 = id#7) || isnull((id#4 = id#7))):- HiveTableRelation `default`.`test_partition1`, org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe, [id#4, name#5], [dt#6]+- Project [id#7]   +- HiveTableRelation `default`.`test_partition2`, org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe, [id#7, name#8], [dt#9]
== Physical Plan ==BroadcastNestedLoopJoin BuildRight, LeftAnti, ((id#4 = id#7) || isnull((id#4 = id#7))):- Scan hive default.test_partition1 [id#4, name#5, dt#6], HiveTableRelation `default`.`test_partition1`, org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe, [id#4, name#5], [dt#6]+- BroadcastExchange IdentityBroadcastMode   +- Scan hive default.test_partition2 [id#7], HiveTableRelation `default`.`test_partition2`, org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe, [id#7, name#8], [dt#9]
通過上述邏輯計劃和物理計劃可以看出,Spark SQL在對not in subquery處理,從邏輯計劃轉換為物理計劃時,會最終選擇BroadcastNestedLoopJoin(對應到Spark源碼中BroadcastNestedLoopJoinExec.scala)策略。

提起BroadcastNestedLoopJoin,不得不提Nested Loop Join,它在很多RDBMS中得到應用,比如mysql。它的工作方式是循環從一張表(outer table)中讀取數據,然后訪問另一張表(inner table,通常有索引),將outer表中的每一條數據與inner表中的數據進行join,類似一個嵌套的循環并且在循環的過程中進行數據的比對校驗是否滿足一定條件。

對于被連接的數據集較小的情況下,Nested Loop Join是個較好的選擇。但是當數據集非常大時,從它的執行原理可知,效率會很低甚至可能影響整個服務的穩定性。

而Spark SQL中的BroadcastNestedLoopJoin就類似于Nested Loop Join,只不過加上了廣播表(build table)而已。

BroadcastNestedLoopJoin是一個低效的物理執行計劃,內部實現將子查詢(select id from test_partition2)進行廣播,然后test_partition1每一條記錄通過loop遍歷廣播的數據去匹配是否滿足一定條件。

private def leftExistenceJoin(   // 廣播的數據    relation: Broadcast[Array[InternalRow]],    exists: Boolean): RDD[InternalRow] = {  assert(buildSide == BuildRight)  /* streamed對應物理計劃中:  Scan hive default.test_partition1 [id#4, name#5, dt#6], HiveTableRelation `default`.`test_partition1`, org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe, [id#4, name#5], [dt#6]  */  streamed.execute().mapPartitionsInternal { streamedIter =>    val buildRows = relation.value    val joinedRow = new JoinedRow
  // 條件是否定義。此處為Some(((id#4 = id#7) || isnull((id#4 = id#7))))    if (condition.isDefined) {      streamedIter.filter(l =>        // exists主要是為了根據joinType來進一步條件判斷數據的返回與否,此處joinType為LeftAnti        buildRows.exists(r => boundCondition(joinedRow(l, r))) == exists      )            // else    } else if (buildRows.nonEmpty == exists) {      streamedIter    } else {      Iterator.empty    }  }}

由于BroadcastNestedLoopJoin的低效率執行,可能導致長時間占用executor資源,影響集群性能。同時,因為子查詢的結果集要進行廣播,如果數據量特別大,對driver端也是一個嚴峻的考驗,極有可能帶來OOM的風險。因此,在實際生產中,要盡可能利用其他效率相對高的SQL來避免使用Not in Subquery。

雖然通過改寫Not in Subquery的SQL,進行低效率的SQL到高效率的SQL過渡,能夠避免上面所說的問題。但是這往往建立在我們發現任務執行慢甚至失敗,然后排查任務中的SQL,發現"問題"SQL的前提下。那么如何在任務執行前,就"檢查"出這樣的SQL,從而進行提前預警呢?

這里筆者給出一個思路,就是解析Spark SQL計劃,根據Spark SQL的join策略匹配條件等,來判斷任務中是否使用了低效的Not in Subquery進行預警,然后通知業務方進行修改。同時,我們在實際完成數據的ETL處理等分析時,也要事前避免類似的低性能SQL。

上述就是小編為大家分享的Spark SQL中Not in Subquery為何低效以及如何規避了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

安塞县| 屯门区| 宾阳县| 石林| 肃南| 高尔夫| 西平县| 正蓝旗| 沿河| 寻乌县| 云南省| 古浪县| 长治市| 南昌市| 禹城市| 天等县| 犍为县| 潜江市| 博爱县| 新余市| 平原县| 霍林郭勒市| 泗水县| 阿城市| 惠州市| 平潭县| 泽库县| 新蔡县| 嵊州市| 建始县| 大城县| 冷水江市| 邓州市| 昌平区| 特克斯县| 望谟县| 西城区| 肥东县| 沾益县| 剑川县| 西昌市|