You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SELECT查询执行步骤疑问:两种JOIN查询性能为何一致?

关于SQL SELECT查询执行步骤与关联查询性能的疑惑

我对SELECT查询的执行步骤存在疑惑,查阅资料得知执行步骤如下:

1. Getting Data (From, Join)
2. Row Filter (Where)
3. Grouping (Group by)
4. Group Filter (Having)
5. Return Expressions (Select)
6. Order & Paging (Order by & Limit / Offset)

我测试了两个关联查询:A表(7000万条记录)与B表(7500万条记录)关联:
第一个查询语句:

select *
from A join B on A.code = B.box_code
where B.box_code = '123'

第二个查询语句:

select *
from A join (select * from B where box_code = '123' ) on A.code = B.box_code

我原以为第一个查询会比第二个慢,因为前者会先关联大量数据再过滤,而后者先过滤B表数据再关联,但实际两者执行速度一致。请问这是为什么?

我搜索后猜测可能与**聚集索引(clustered index)**有关,但不确定。另外还有一个问题:为何聚集索引能让WHERE条件在JOIN之前执行?我原本认为查询会先执行JOIN再执行WHERE,我的理解误区在哪里?

附执行计划图:

  • 第一个查询执行计划:第一个查询执行计划
  • 第二个查询执行计划:第二个查询执行计划

问题解答

1. 为什么两个查询执行速度一致?

这是因为数据库的查询优化器会自动改写你的查询,选择最优的执行路径,不会严格按照你写的SQL语句顺序执行。

你的第一个查询看起来是先关联A和B再过滤,但优化器会识别出WHERE B.box_code = '123'这个条件可以提前应用——先从B表中筛选出box_code='123'的记录(这一步数据量极小),再和A表关联,最终的执行逻辑和你第二个手动提前过滤的查询完全一致。

从你提供的两张执行计划图也能看出来,两个查询的执行流程是相同的:都是先筛选B表的目标数据,再和A表做关联。优化器并不会被SQL的写法束缚,它会根据表的索引、数据分布等信息,自动选择成本最低的执行方案。

2. 你的理解误区:执行步骤不是固定的“先JOIN后WHERE”

你查到的那套执行步骤是逻辑执行顺序,不是数据库实际的物理执行顺序。逻辑顺序是用来帮助你理解SQL的语义,而数据库实际执行时,优化器会对逻辑步骤进行重排,只要最终结果符合SQL的语义即可。

当B表的box_code字段上有聚集索引(或普通索引)时,优化器可以快速定位到box_code='123'的记录:

  • 聚集索引的叶子节点存储了整行数据,所以通过聚集索引找到目标值后,直接就能拿到B表的完整行数据,不需要再回表查询;
  • 这个筛选操作的成本远低于先关联两张大表再过滤,所以优化器会优先执行这个WHERE条件,再做JOIN。

简单说:逻辑执行顺序是“先JOIN后WHERE”,但物理执行时,优化器会把能提前过滤的条件推到JOIN之前,这叫谓词下推(Predicate Pushdown),而索引(包括聚集索引)是让这个优化能够高效执行的关键。


内容的提问来源于stack exchange,提问作者Hưng hoàng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:15:35