mysql SQL查询是如何执行的_mysql执行阶段解析

来源:这里教程网 时间:2026-02-28 20:51:26 作者:

SQL 查询在 MySQL 中到底经历了哪些阶段

MySQL 执行一条

SELECT
语句,并不是直接去磁盘捞数据然后返回。它会经过多个明确的内部阶段,每个阶段都可能成为性能瓶颈或出错源头。

典型流程是:连接 → 解析 → 优化 → 执行 → 返回结果。其中「解析」和「优化」阶段用户不可见但影响极大;「执行」阶段的行为则直接受索引、表结构、隔离级别等约束。

为什么 EXPLAIN 看到的执行计划和实际执行不一致

EXPLAIN
只模拟优化器的预判路径,不真正执行 SQL,所以它不会反映运行时才暴露的问题:

统计信息过期(
ANALYZE TABLE
未触发,导致优化器误判行数)
绑定变量值不同引发不同的执行计划(尤其在
PREPARE/EXECUTE
场景下)
查询缓存(MySQL 8.0 已移除)或 Query Cache 开关状态影响是否走缓存路径 临时表或文件排序实际发生时,
EXPLAIN
不显示磁盘 I/O 开销

从 slow_log 能看出哪个阶段出了问题

慢查询日志里关键字段如

Rows_examined
Rows_sent
tmp_tables
sort_merge_passes
都指向具体阶段:

Rows_examined
显著大于
Rows_sent
→ 扫描过多行,可能是缺少索引或索引未命中(解析/执行阶段低效)
tmp_tables > 0
tmp_table_sizes
较大 → 优化器选择了基于磁盘的临时表(优化阶段决策失败)
sort_merge_passes > 0
→ 文件排序次数多,说明
sort_buffer_size
不足或无法利用索引排序(执行阶段资源受限)
Query_time
高但
Lock_time
也高 → 锁等待发生在执行阶段前的加锁环节(InnoDB 行锁/间隙锁竞争)

optimizer_trace 能帮你定位优化器“想错了”的地方

开启

optimizer_trace
后,MySQL 会记录优化器每一步的代价估算和最终选择依据,对理解“为什么没走索引”特别有用:

需先执行
SET optimizer_trace="enabled=on"
,再运行目标 SQL
结果存在
information_schema.OPTIMIZER_TRACE
表中,查
TRACE
字段 JSON 内容
重点关注
rows_estimation
中各访问路径的预估行数、
considered_execution_plans
中被放弃的理由(比如 "Range checked for each record (index map: 0x1)")
注意该功能有性能开销,仅用于诊断,不要长期开启

真正卡住查询的,往往不是语法写错,而是优化器在毫秒级内做的一个“看起来合理”的错误选择——而这个选择背后,是统计信息、索引设计、参数配置共同作用的结果。盯着

EXPLAIN
optimizer_trace
对比看,比反复改 SQL 更有效。

相关推荐