我有一个如下所示的SQL查询-
A left JOIN B Left Join C Left JOIN D
说表A是大表,而表B,C,D是小表。
Spark联接将执行- A和B,随后的结果将与C和D结合在一起
或者
Spark会自动优化,即它将加入B,C和D,然后 结果将与A结合在一起。
我的问题是执行或加入评估的顺序是什么?它是从左到右还是从右到左?
答案 0 :(得分:2)
Spark如果可以访问有关那些连接基数的信息,则可以优化连接顺序。
例如,如果这些是镶木地板表或缓存的数据帧,则它可以估算表的总数,并可以对连接顺序进行重新排序以降低成本。如果“表”是jdbc数据帧,则Spark可能没有行计数信息。
Spark Query Optimizer也可以选择其他联接类型,以防其具有统计信息(例如,它可以广播所有较小的表,并运行broadcast hash join
而不是sort merge join
)。
如果统计信息不可用,则它将按照SQL查询中的顺序进行操作,例如从左到右。
更新:
我最初错过了查询中的所有联接都是外部联接(left
等同于left outer
)。
通常外部连接不能重新排序,因为这会更改查询结果。我之所以说“正常”,是因为有时Spark Optimizer可以将外部联接转换为内部联接(例如,如果您有一个WHERE
子句可以过滤掉NULL-see conversion logic here)。
为确保答案的完整性,连接的重新排序由两个不同的代码路径驱动,具体取决于是否启用了 Spark CBO (spark.sql.cbo.enabled
首先出现在Spark 2.2中,默认情况下处于关闭状态) )。如果spark.sql.cbo.enabled
= true和spark.sql.cbo.joinReorder.enabled
= true(默认情况下也处于关闭状态),并且统计信息可以通过ANALYZE TABLE .. COMPUTE STATISTICS
手动获得/收集,则重新排序基于我上面提到的联接的估计基数。
证明重新排序仅适用于INNER JOINS is here(以CBO为例)。
更新2 :示例查询显示外部联接的重新排序会产生不同的结果,因此外部联接永远不会重新排序:
答案 1 :(得分:1)
join
的解释顺序与内部联接无关紧要。但是,这对于外部联接可能很重要。
您的逻辑等同于:
FROM ((A LEFT JOIN
B
) ON . . . LEFT JOIN
C
ON . . . LEFT JOIN
)
D
ON . . .
考虑LEFT JOIN
链的最简单方法是,它们保留第一个表中的所有行,并保留后续表中匹配行的列。
请注意,这是代码的解释。 SQL优化器可以自由地以任何顺序重新排列JOIN
以获得相同的结果集(尽管使用外部联接通常比使用内部联接的可能性小)。