898 字
约 2 分钟
8
S11-J03 · Explain 逐列读
适用读者:看得懂
EXPLAIN但不确定"哪一列决定性能"的人。
前置:S11-J02。
实测环境:MySQL 8.0.46(2026-11-05)。
覆盖旧文:1543(28) 1566(270) = 298 点。
覆盖扩展:E-S11-017(type等级与filtered)。
上一篇:S11-J02 · 索引失效的六种情况
下一篇:S11-J04 · 慢查询排查与调优。
1. 一句话结论
EXPLAIN 里有四个关键列:type(访问方式)、key(用了哪个索引)、rows(预估扫描行数)、Extra(是否回表/是否临时表/是否文件排序)。
实测样本(同一张表,两种写法):
-- 有索引
type: ref key: idx_age rows: 250 Extra: NULL
-- 函数包裹
type: ALL key: NULL rows: 20000 Extra: Using where
2. type 的等级(从好到差)
| type | 含义 | 备注 |
|---|---|---|
system/const |
常量(主键/唯一索引等值) | 最快 |
eq_ref |
联表时被驱动表用唯一索引 | 很好 |
ref |
非唯一索引等值 | 常见的好情况 |
range |
索引范围扫描 | 尚可(like 'x%'、between) |
index |
全索引扫描 | 读整个索引(前导模糊常见) |
ALL |
全表扫描 | 最差 |
index_merge |
合并多个索引 | 视情况 |
判据:"出现 ALL 就该问为什么";出现 index 要问"能不能变成 range"。
3. rows 与 filtered
| 列 | 含义 | 坑 |
|---|---|---|
rows |
预估扫描行数 | 基于统计信息,可能不准 |
filtered |
扫描后剩余百分比 | rows × filtered% ≈ 实际返回 |
实测:rows=250(20,000 行里 age=30 的约 250 条,因为 n%80)。
"rows 准不准" 取决于统计信息新鲜度:ANALYZE TABLE 可刷新。
4. Extra 的常见值(E-S11-017)
| Extra | 含义 | 好/坏 |
|---|---|---|
Using index |
覆盖索引,不回表 | ✅ 好 |
Using where |
服务器层再过滤 | 中性 |
Using index condition |
索引下推(ICP) | ✅ 好 |
Using temporary |
用了临时表 | ❌ 常见于 group by/distinct |
Using filesort |
额外排序 | ❌ 常见于无索引的 order by |
Using join buffer |
联表无索引 | ❌ |
Using MRR |
多范围读 | ✅ 视情况 |
"Using filesort 一定慢吗":不一定——小结果集排序很快;但它是"排序没走索引"的信号。
5. 两种 EXPLAIN
| 命令 | 输出 |
|---|---|
EXPLAIN |
预估计划 |
EXPLAIN ANALYZE(8.0.18+) |
真实执行时间与行数(会真的跑) |
判据:"预估和实际差得多吗?" 差得多 → 统计信息有问题,或优化器估算错。
6. 五个误区
| 误区 | 真相 |
|---|---|
"rows 是精确值" |
是估算 |
"type=index 比 ALL 好很多" |
都是线性扫描,只是扫索引 |
"Using where 是坏信号" |
中性(服务器层过滤) |
"Using filesort 一定慢" |
小结果集很快 |
"EXPLAIN 就是真实执行" |
预估;ANALYZE 才真跑 |
7. 自检
type从好到差排序(至少六个)?rows与filtered怎么配合看?Using index与Using index condition的区别?Using filesort说明什么?EXPLAIN与EXPLAIN ANALYZE的差别?
8. 下一篇
S11-J04 · 慢查询排查与调优
Explain 讲完,下一篇把工具串起来:慢日志 → EXPLAIN → 改写 → 验证的闭环。
本篇属于系列《S11 · 数据库与 SQL》。旧文来源:A-1543/1566;扩展点 E-S11-017。EXPLAIN 输出为 MySQL 8.0.46 实测。
S11-J03 · Explain 逐列读
https://www.clxhxhhr.top/posts/5333/ 评论
0 条
还没有评论,先写一条吧。