2016-06-12 48 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")