Presto/Spark SQL中Left Join效率对比:两种写法孰优孰劣?
Presto/Spark SQL中多表LEFT JOIN两种写法的性能对比
直接给结论:这两种写法在Presto和Spark SQL中没有性能差异,具体原因如下:
核心逻辑:CTE是语法糖,会被优化器内联
方案2的CTE写法只是逻辑层面的分步关联,但现代SQL引擎(包括Presto、Spark SQL)的查询优化器会自动对这种链式引用的CTE进行内联优化——也就是把分步的CTE展开成和方案1完全一致的逻辑执行计划,不会真的分步生成中间表再做关联,底层执行逻辑完全相同。
两种写法的语义完全一致
不管是方案1的一次性关联,还是方案2的分步CTE,最终表达的语义都是:以TABLEA为左表,依次与TABLEB、TABLEC、TABLED执行LEFT JOIN,关联条件均为id匹配。优化器会基于数据分布、统计信息(比如各表的id基数、数据量)选择最优的物理执行策略(比如哈希连接、广播连接的选择,关联顺序的调整等),和写法无关。
真正影响性能的优化点
如果想优化这类多表关联的性能,重点不在写法,而在这些细节:
- 避免使用
SELECT *,只查询实际需要的字段,减少数据传输和处理的开销 - 确保关联字段
id有准确的统计信息,帮助优化器做出最优决策 - 根据表的大小选择合适的连接策略(比如Spark中对小表开启广播连接,Presto中调整连接算法配置)
两种写法的代码示例
方案1:
SELECT * FROM TABLEA a LEFT JOIN TABLEB b ON a.id=b.id LEFT JOIN TABLEC c ON a.id=c.id LEFT JOIN TABLED d ON a.id=d.id
方案2(CTE写法):
WITH tablea_b as ( SELECT * FROM TABLEA a LEFT JOIN TABLEB b ON a.id=b.id) , tablea_b_c as ( SELECT * FROM tablea_b a LEFT JOIN TABLEC c ON a.id=c.id) , tablea_b_c_d as ( SELECT * FROM tablea_b_c a LEFT JOIN TABLED d ON a.id = d.id) SELECT * FROM tablea_b_c_d
内容的提问来源于stack exchange,提问作者Shlim
相关产品推荐
相关产品推荐

