直接看explain的type、key、rows、extra四列即可定位多数性能瓶颈:type=all或index需警惕索引缺失,key为空表示索引失效,rows远大于结果行数说明扫描低效,extra含using filesort/temporary必须优化。

直接看 EXPLAIN 输出里的 type、key、rows 和 Extra 这四列,就能快速定位绝大多数性能瓶颈。其他字段(如 id、select_type)主要用于理解执行逻辑,不直接影响性能判断。
type 值低于 range 就要警惕
type 是访问类型,反映是否用索引、怎么用索引。它从优到劣依次是:system > const > eq_ref > ref > range > index > ALL。
常见问题场景:
-
type = ALL:全表扫描,最常见性能杀手,尤其在大表上;优先检查WHERE条件字段有没有索引,或索引是否被函数/隐式转换破坏 -
type = index:索引全扫描,比ALL稍好但仍是低效操作;说明走了索引,但没用上索引的查找能力(比如ORDER BY无索引、SELECT *导致回表开销大) -
type = range是底线,表示用了索引范围扫描;再往上(ref及以上)才算“合理使用索引”
key 为空或与预期不符说明索引失效
key 显示 MySQL 实际选择的索引。如果它是 NULL,或者和你预设的索引不一致,基本可以断定索引没被用上。
典型原因包括:
-
WHERE中对索引字段用了函数,如WHERE YEAR(create_time) = 2024→ 改成WHERE create_time BETWEEN '2024-01-01' AND '2024-12-31' - 存在隐式类型转换,如
WHERE user_id = '123'(user_id是INT),MySQL 会放弃索引 - 联合索引未满足最左前缀,如索引是
(a, b, c),但查询只用了WHERE b = 1或WHERE c = 1 -
possible_keys有值但key是NULL:优化器评估后认为走索引反而更慢(比如查了 80% 行),这时得结合rows和实际数据分布判断
rows 值远大于实际结果集行数就是隐患
rows 是优化器估算的扫描行数,不是精确值,但极具参考价值。它和真实性能强相关:
- 如果
rows = 100000但最终只返回 10 行,大概率存在“查得多、用得少”的问题,比如缺失索引、条件写法导致无法下推 -
rows偏高时,先看type是否为ALL或index;再确认key是否生效;最后检查统计信息是否过期(可运行ANALYZE TABLE table_name更新) - 注意:当
rows很小(比如 1 或 2)但查询仍慢,问题可能不在扫描本身,而在锁等待、磁盘 I/O 或网络传输
Extra 出现 Using filesort 或 Using temporary 必须处理
Extra 是执行过程中的附加行为,两个关键词是硬性红线:
-
Using filesort:MySQL 无法利用索引完成排序,需额外排序操作;常见于ORDER BY字段没索引,或索引顺序与排序要求不匹配(如索引(a, b),却ORDER BY b) -
Using temporary:创建临时表,多见于GROUP BY、DISTINCT、UNION或某些JOIN场景;若出现在简单查询里,说明语句结构或索引设计有问题 -
Using index是好消息,代表覆盖索引,无需回表;但要注意它和Using where共存时,说明 WHERE 条件部分用了索引、部分没用上
真正难的不是看懂单个字段,而是把 type、key、rows、Extra 四者交叉验证——比如 type = ref 但 rows 极高,说明索引区分度差;key 有值但 Extra 仍有 Using filesort,说明排序字段未纳入索引。这些组合信号,才是调优的关键入口。











