Spark - SQL联接是否会创建所有组合?

时间:2018-04-10 13:39:50

标签: sql apache-spark apache-spark-sql

这个问题适用于Spark,但我假设(?)它可能更常见于任何SQL表连接。

假设我们有表A和B.然后我们发出这个命令:

select a.* from a inner join b on a.col1 - b.col1 <= 0.5

在幕后,首先创建一个笛卡尔积,然后根据a.col1 - b.col1&lt; = 0.5的条件进行过滤。或者评估表之间的每个行组合,然后再返回标准是的,生成的行返回了吗?

1 个答案:

答案 0 :(得分:1)

是。连接条件(不是基于值的相等性(用户定义的函数调用的结果,对来自不同表的列计算的值以及非相等性比较运算符)无法优化,并且被评估为笛卡尔积,然后进行选择。

如果您检查生成的执行计划,很容易确认。例如:

import org.apache.spark.sql.functions._

spark.range(1000).select(rand() as "col1").createOrReplaceTempView("a")
spark.range(1000).select(rand() as "col1").createOrReplaceTempView("b")

spark.sql("select a.* from a inner join b on a.col1 - b.col1 <= 0.5").explain
// == Physical Plan ==
// *Project [col1#9]
// +- BroadcastNestedLoopJoin BuildRight, Inner, ((col1#9 - col1#16) <= 0.5)
//    :- *Project [rand(3279117551830311353) AS col1#9]
//    :  +- *Range (0, 1000, step=1, splits=4)
//    +- BroadcastExchange IdentityBroadcastMode
//       +- *Project [rand(-3185472069145487350) AS col1#16]
//          +- *Range (0, 1000, step=1, splits=4)

同样如果你禁用广播联接:

spark.conf.set("spark.sql.autoBroadcastJoinThreshold", -1)

spark.sql("select a.* from a inner join b on a.col1 - b.col1 <= 0.5").explain
// == Physical Plan ==
// *Project [col1#9]
// +- CartesianProduct ((col1#9 - col1#16) <= 0.5)
//    :- *Project [rand(3279117551830311353) AS col1#9]
//    :  +- *Range (0, 1000, step=1, splits=4)
//    +- *Project [rand(-3185472069145487350) AS col1#16]
//       +- *Range (0, 1000, step=1, splits=4)