两个仅ve表LEFT JOIN位置不同的SQL查询:输出是否一致?性能为何差异大?
两个SQL查询对比
Query 1
select * from a LEFT JOIN p ON a.product_id = p.web_id LEFT JOIN m ON p.manufacturer_id = m.web_id LEFT JOIN a add ON a.address_id = add.web_id LEFT JOIN c ON c.web_id = a.owner_id LEFT JOIN a ca ON c.main_address_id = ca.web_id LEFT JOIN d ON a.web_id = d.equipment_id LEFT JOIN s ON d.last_segment_id = s.web_id LEFT JOIN oh ON s.order_header_id = oh.web_id LEFT JOIN f ON s.folder_id = f.web_id LEFT JOIN ve on a.web_id = ve.equipment_id where ve.date_updated >= now() - interval '10000 min'
Query 2
select * from a LEFT JOIN p ON a.product_id = p.web_id LEFT JOIN m ON p.manufacturer_id = m.web_id LEFT JOIN ve on a.web_id = ve.equipment_id LEFT JOIN a add ON a.address_id = add.web_id LEFT JOIN c ON c.web_id = a.owner_id LEFT JOIN a ca ON c.main_address_id = ca.web_id LEFT JOIN d ON a.web_id = d.equipment_id LEFT JOIN s ON d.last_segment_id = s.web_id LEFT JOIN oh ON s.order_header_id = oh.web_id LEFT JOIN f ON s.folder_id = f.web_id where ve.date_updated >= now() - interval '10000 min'
问题解答
输出是否始终一致?
是的,两个查询的输出完全一致。
WHERE子句中ve.date_updated >= now() - interval '10000 min'的条件,会将原本的LEFT JOIN ve隐式转换为INNER JOIN——只有a表中存在匹配的ve记录,且该ve记录满足时间要求时,这条a记录才会被保留。无论ve表的JOIN位置在前还是在后,最终逻辑都是筛选出符合条件的a记录,再LEFT JOIN其他关联表,因此结果集没有差异。
性能差异的核心原因
两者的性能差距来自数据库执行过程中中间结果集的规模差异:
Query 1的高效执行路径
Query 1将ve表的JOIN放在最后,数据库优化器可以优先执行过滤操作:
- 先扫描ve表,只保留
date_updated符合条件的小批量数据; - 用这个小数据集关联a表,得到远小于2000万条的a记录子集;
- 基于这个精简后的子集,再依次关联其他表。
整个过程中间数据量可控,IO和计算成本低,因此执行速度快。
Query 2的低效执行路径
Query 2提前关联ve表:
- 先将2000万条a记录与p、m、未过滤的ve表关联,生成的中间结果集接近2000万条;
- 后续带着这个庞大的中间集去关联其他所有表,每一步都要处理大量数据,资源消耗剧增;
- 虽然最后会通过WHERE条件过滤掉不符合的ve记录,但此时已经浪费了大量资源在无效的关联操作上,导致耗时大幅增加。
内容的提问来源于stack exchange,提问作者Cfc
相关产品推荐
相关产品推荐

