优化器不是读懂业务的智能系统,它只是一个成本估算器。它根据统计信息、索引基数、直方图和条件选择率,估算不同访问路径的代价,然后选择看起来更便宜的那条。
所以“优化器选错了”不是结论,只是现象。真正要问的是:它凭什么认为另一条路径更便宜,统计信息哪里失真,数据分布哪里偏离了平均值。
先把机制边界说清楚
优化器不是读懂业务的智能系统,它是一个成本估算器。它根据表统计信息、索引基数、直方图、条件选择率、回表成本、排序成本,估算不同执行路径的代价,然后选择看起来最便宜的那条。
整体路径
上面这张图先看粗线条:宏观上,优化器统计信息是一条从“真实数据分布”到“执行计划”的估算链路。真实表数据先通过采样和统计变成基数、页数、直方图等元信息;优化器再用这些元信息估算 rows 和 cost;最后生成执行计划。链路里的任何估算失真,都会反映成选错索引、扫描行数异常或排序代价判断错误。
底层流程
底层拆解先看数据结构。「优化器统计信息」至少涉及下面几类结构:
- 索引基数:描述不同键值的大致数量,影响等值过滤估算。
- 持久化统计信息:InnoDB 保存的表和索引统计元数据。
- 直方图:MySQL 8.0 用来描述非索引列或倾斜列分布。
- 成本模型:把扫描、回表、排序、临时表等动作折算成代价。
再看完整执行流程:
- 解析 SQL 后列出候选访问路径。
- 读取表和索引统计信息。
- 估算每个条件的过滤率和 rows。
- 叠加回表、排序、临时表等成本。
- 选择总代价最低的执行计划。
取舍与边界
版本差异上,MySQL 5.7 主要依赖传统索引统计,遇到数据倾斜时容易误判。MySQL 8.0 引入直方图、持久化统计增强和更丰富的 optimizer trace,能更好解释为什么选这条路径,但估算本质没有变。
统计信息最大短板是它永远是近似值。采样页太少、数据刚大量导入、热点值极端集中、多个条件高度相关,都可能让 rows 估算偏离真实值。优化器不是不努力,而是它看到的世界已经失真。
典型问题:用机制化例子排查
优化器选错索引,可以先怀疑统计信息和数据分布:平均选择性看起来不错,不代表热点值也便宜。排查重点是 rows 估算和真实扫描量之间的差距。
可以落到这些动作:
- 先对比 explain rows 和实际扫描行数,判断是否是估算失真。
- 数据大批量变更后执行 ANALYZE TABLE 刷新统计信息。
- MySQL 8.0 对倾斜列可以考虑直方图,但要控制维护成本。
- FORCE INDEX 只适合临时止血,长期方案应回到索引和查询模型。
收束:优化器相信它看到的世界
优化器统计信息决定了 MySQL 眼里的世界。排障时不要只问“为什么不用这个索引”,要问“它为什么以为另一条路径更便宜”。
关于十三Tech
我是十三,All in AI Agent 方向的架构师,专注 AI 工程实践。
我相信 AI 是程序员的最佳搭档,也希望帮助每一位开发者更好地驾驭 AI。
如果你想继续跟完这套「图解 MySQL」,欢迎关注公众号 「十三Tech」。后续会继续按机制、图解和实战排查这条线更新。

