禁用当查询计划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例如笔记本电脑



这篇文章有用吗?