估算行数与过滤比例
在执行计划里,有一列表示「预计要扫描多少行」,另一列表示「过滤之后还剩百分之多少」。两者相乘,就是估算传给下一步的行数,也是优化器判断后续用嵌套循环还是哈希连接的主要依据。读这两个数的意义在于定位低效过滤:扫描几千行最后只留下几十行,说明大部分工作被浪费在读取与丢弃上,通常意味着过滤条件没能下推到索引层。
基本信息
| 适用平台 | MySQL 8.0(经典格式计划输出) |
|---|---|
| 估算行数列 | 预计扫描的行数,不是最终返回行数 |
| 过滤比例列 | 以百分比表示过滤后剩余比例,范围零到一百 |
| 二者关系 | 相乘得到传给下一步的估算行数 |
| 前置动作 | 统计信息陈旧时先重新采样再对比 |
典型使用场景
- 连接变慢:确认驱动侧产出的估算行数是否被高估或低估
- 索引评估:判断过滤列该不该加进复合索引
- 参数化差异排查:同一语句不同参数的计划差异是否来自过滤比例
- 改写验证:改写后对比估算与实际行数的接近程度
- 优化决策留痕:把计划前后对比记录进变更文档
读取与更新统计
读取与更新统计
-- 查看计划中的估算行数与过滤比例
EXPLAIN SELECT * FROM orders
WHERE user_id = 100 AND status = 'paid';
-- 假设输出显示:扫描行数 500,过滤比例 10.00
-- 含义:预计扫 500 行,过滤后约剩 50 行传给下一步
-- 统计信息陈旧时先刷新再对比,避免在旧估算上做决策
ANALYZE TABLE orders;
EXPLAIN SELECT * FROM orders
WHERE user_id = 100 AND status = 'paid';
-- 需要真实执行数据时用分析模式(会真实执行语句)
-- EXPLAIN ANALYZE SELECT ... ;
-- 想让过滤在索引层完成,把过滤列加入复合索引后复看计划
-- ALTER TABLE orders ADD INDEX idx_user_status (user_id, status);两列读法
| 观察项 | 含义 | 异常信号 |
|---|---|---|
| 估算行数 | 预计扫描行数 | 与真实行数差一两个数量级 |
| 过滤比例 | 过滤后剩余百分比 | 数值很低说明大量行读完即丢 |
| 两者乘积 | 传给下一步的估算行数 | 偏大时后续可能被选中较重的算法 |
| 索引使用列 | 实际选择的索引 | 显示未使用索引说明条件不匹配 |
| 额外信息列 | 排序、下推等提示 | 出现临时表说明中间结果偏大 |
过滤比例是一个百分比,不是行数:显示百分之十意味着大约剩下十分之一的行,误解成十行会把估算规模判断错一个量级。
估算行数是基于统计信息的推测,数据分布倾斜严重或统计信息过期时偏差很大。判断优化效果时要把估算与实际放在一起看,只看估算容易得出相反结论。