EXPLAIN 的 type 值反映索引使用质量,理想为 ref 或 range;ALL 和 index 表示未有效过滤,需检查索引设计、WHERE 条件是否符合最左前缀原则及是否存在函数/类型转换等导致索引失效的因素。

怎么看 EXPLAIN 里的 type 值是否合理
type 表示 MySQL 如何查找行,它直接反映索引使用质量。值从好到差大致是:system ≈ const > eq_ref > ref > range > index > ALL。
重点盯住 ALL 和 index:前者全表扫描,后者虽走索引但仍是全索引扫描(等价于没过滤),都意味着查询没真正利用索引的筛选能力。
-
ref或range通常是健康信号,说明用了索引做等值或范围查找 -
eq_ref多见于主键/唯一索引关联,效率最高 - 如果本该走
ref却显示ALL,先检查WHERE条件列是否在索引最左前缀上 -
type是index但rows很大,大概率是只用索引做覆盖扫描,没用于过滤——得看key和Extra配合判断
key 显示 NULL 或非预期索引名的原因
key 字段明确告诉你优化器实际选了哪个索引。它为 NULL 意味着完全没走索引;显示一个你没想用的索引,则说明优化器认为它更优(或你的目标索引不可用)。
- 常见原因包括:
WHERE中用了函数(如YEAR(created_at))、隐式类型转换(如字符串字段查数字)、OR条件中部分分支无法用索引 - 复合索引只对最左前缀生效:
INDEX(a, b, c)支持a、a,b、a,b,c查询,但不支持单独b或b,c - 如果强制指定索引(
USE INDEX)后key变了但性能更差,说明优化器原本的选择未必错——别盲目干预
rows 数值远大于实际结果集说明什么
rows 是优化器预估的扫描行数,不是返回行数。它偏大通常意味着索引选择不当或统计信息过期。
- 若
rows = 100000但SELECT COUNT(*)实际只有 200 行,优先执行ANALYZE TABLE table_name更新统计信息 -
rows和EXPLAIN FORMAT=JSON中的filtered值相乘,约等于最终输出行数。比如rows=10000、filtered=10.00,说明大约返回 1000 行 - 复合索引中,如果
WHERE只用了右半部分(如INDEX(a,b)中只查b = ?),rows会接近全表,因为索引无法跳过a
Extra 里哪些提示真危险
Extra 是关键线索,尤其几个带“Using”的提示:
-
Using filesort:需要额外排序,没走索引排序。即使ORDER BY字段有索引,也要求顺序和索引顺序一致且无范围条件干扰 -
Using temporary:创建临时表,常见于GROUP BY+ 非索引字段、DISTINCT、UNION。和Using filesort同时出现,基本可判定性能瓶颈 -
Using index:好事,表示走了覆盖索引(只查索引就拿到所有字段),不用回表 -
Using where; Using index:更好,既覆盖又做了索引层过滤 -
Using index condition:启用了 ICP(索引条件下推),说明部分WHERE条件下推到存储引擎层执行,减少回表次数
真正要警惕的是 Using filesort 和 Using temporary 共存,这时加索引往往治标不治本,得重审查询逻辑或考虑物化中间结果。










