我在Spark SQL中有一个查询正在使用广播连接,因为我的表b小于spark.sql.autoBroadcastJoinThreshold.
但是,如果我将完全相同的select查询放入CTAS查询中,那么由于某种原因它不会使用广播连接.
select查询如下所示:
select id,name from a join b on a.name = b.bname;
对此的解释看起来如下:
== Physical Plan ==
Project [id#1,name#2]
+- BroadcastHashJoin [name#2], [bname#3], BuildRight
:- Scan ParquetRelation: default.a[id#1,name#2] InputPaths: ...
+- ConvertToUnsafe
+- HiveTableScan [bname#3], MetastoreRelation default, b, Some(b)
然后我的CTAS看起来像这样:
create table c as select id,name from a join b on a.name = b.bname;
并且对此的解释返回:
== Physical Plan ==
ExecutedCommand CreateTableAsSelect [Database:default}, TableName: c, InsertIntoHiveTable]
+- Project [id#1,name#2]
+- Join Inner, Some((name#2 = bname#3))
:- Relation[id#1,name#2] ParquetRelation: default.a
+- MetastoreRelation default, b, Some(b)
是否期望不使用广播联接作为CTAS查询的一部分的选择查询?如果没有,有没有办法强制CTAS使用广播加入?
最佳答案 如果你的问题是关于Spark创建两个不同的物理计划的原因,那么这个答案将没有用.我在Spark的优化器中观察到了很多敏感性,其中相同的SQL片段导致有意义的不同物理计划,即使不明显为什么会这样.
但是,如果您的问题最终是关于如何使用广播连接执行CTAS,那么这里是一个我已经多次使用的简单解决方法:将您喜欢的计划注册为临时表(或者如果您使用SQL则查看控制台)然后使用来自tmp_tbl的SELECT *作为查询来提供CTAS.
换句话说,像:
sql("select id, name from a join b on a.name = b.bname").registerTempTable("tmp_joined")
sql("create table c as select * from tmp_joined")