apache-spark – 为什么Spark 1.6.1中的Spark SQL不在CTAS中使用广播连接?

我在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")
点赞