




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 共存,这时加索引往往治标不治本,得重审查询逻辑或考虑物化中间结果。