2016-06-12 81 views
4

我有一个正在使用广播连接的Spark SQL查询,因为我的表b小于spark.sql.autoBroadcastJoinThreshold为什么Spark 1.6.1中的Spark SQL不使用CTAS中的广播连接?

但是,如果我将完全相同的select查询放入CTAS查询中,那么由于某种原因它不使用广播连接。

的选择查询看起来是这样的:

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使用广播连接?

回答

1

如果你的问题是关于为什么Spark创建两个不同的物理计划的原因,那么这个答案不会有帮助。我在Spark的优化器中观察到了很多敏感性,即相同的SQL片段导致有意义的不同物理计划,即使它不是明显的原因。但是,如果你的问题最终是关于如何用广播连接执行CTAS,那么这里有一个我已经多次使用的简单解决方法:用你喜欢的计划作为临时表注册查询(或者如果你查看正在使用SQL控制台),然后使用SELECT * from tmp_tbl作为查询来提供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")