SQL是从右到左还是从左到右计算?

时间:2019-12-26 17:52:31

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

我有一个如下所示的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结合在一起。

我的问题是执行或加入评估的顺序是什么?它是从左到右还是从右到左?

2 个答案:

答案 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 :示例查询显示外部联接的重新排序会产生不同的结果,因此外部联接永远不会重新排序:

outer joins join order changes result

答案 1 :(得分:1)

join的解释顺序与内部联接无关紧要。但是,这对于外部联接可能很重要。

您的逻辑等同于:

FROM ((A LEFT JOIN
       B
      ) ON . . . LEFT JOIN
      C
      ON . . . LEFT JOIN
     )
     D
     ON . . .

考虑LEFT JOIN链的最简单方法是,它们保留第一个表中的所有行,并保留后续表中匹配行的列。

请注意,这是代码的解释。 SQL优化器可以自由地以任何顺序重新排列JOIN以获得相同的结果集(尽管使用外部联接通常比使用内部联接的可能性小)。