【发布时间】:2018-04-10 22:00:01
【问题描述】:
这个问题是针对 Spark 的,但我假设(?)它可能对任何 SQL 表连接都更通用。
假设我们有表 A 和 B。然后我们发出这个命令:
select a.* from a inner join b on a.col1 - b.col1 <= 0.5
在幕后,首先创建一个笛卡尔积,然后根据 a.col1 - b.col1
【问题讨论】:
标签: 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
【问题讨论】:
标签: sql apache-spark apache-spark-sql
是的。不基于相等值(用户定义的函数调用的结果、在不同表中的列上计算的值以及不相等的比较运算符)的连接条件无法优化,并且被评估为笛卡尔积,然后是选择。
如果您检查生成的执行计划,很容易确认。例如:
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)
【讨论】: