SQL查询优化:子查询写法与直接表关联的执行效率对比
两种SQL关联查询的性能对比结论
在主流现代关系型数据库(MySQL 8.0+、PostgreSQL 10+、Oracle 11g+、SQL Server 2017+等)的默认配置下,这两种写法的执行耗时没有可感知的差异,最终执行效率完全一致。
背后的核心原理
两种写法性能一致的核心原因是数据库的查询优化器会自动做等价改写,不会严格按你写SQL的字面顺序执行:
- 第一种写法里
from后接的子查询属于无过滤、无聚合、无排序的纯投影子查询,优化器会自动做**子查询展开(Subquery Unnesting)**优化,不会真的先执行子查询生成两张临时派生表再做关联。 - 优化器改写后,两种SQL会生成完全相同的执行计划:都会在关联阶段只读取需要的字段——也就是table1的
key、A、B、C,table2的key、D、E、F,不会读取两表中其他未被选择的字段;如果key字段上建了关联索引,两种写法都会走相同的索引关联逻辑,扫描行数、关联方式、IO开销完全一致。
存在性能差异的特殊场景
只有在使用非常老旧的数据库版本时,才会出现明显性能差:
- 比如MySQL 5.5及更早版本、部分十几年前的传统商业库老版本,优化器不支持对这类简单子查询做展开改写,会严格按SQL字面逻辑执行:先全表扫描捞出两个子查询的所有结果生成内存/磁盘临时表,再在临时表上做关联。这种场景下第一种写法会更慢——因为临时表默认没有关联键的索引,关联阶段的计算开销远大于直接关联有索引的原表,数据量越大差异越明显。
实操验证方式
你可以直接在自己用的数据库里执行执行计划查看命令验证:
- MySQL/PostgreSQL用
EXPLAIN + 你的SQL语句 - Oracle用
EXPLAIN PLAN FOR + 你的SQL语句 - SQL Server用
SET SHOWPLAN_XML ON后执行SQL
只要两种写法的执行计划中关联顺序、扫描方式、索引命中、扫描行数、额外执行信息完全一致,就不存在性能差异。
注意:不要在这类子查询里额外加无意义的
ORDER BY、GROUP BY、DISTINCT逻辑,这类操作会阻碍优化器的子查询改写,真的生成临时结果集,反而拖慢查询速度。
内容的提问来源于stack exchange,提问作者o_yeah
相关产品推荐
相关产品推荐

