mysql执行计划核心是看type、key、rows、extra:type判访问方式(all需优化),key与rows联判索引有效性,extra揭真实瓶颈(如using filesort需覆盖索引)。

面试中问到 MySQL 执行计划,核心就三点:怎么看、怎么看懂、怎么用它去优化。不是背字段含义,而是能结合 type、key、rows、Extra 这几个关键列,快速判断一条 SQL 的真实执行路径和潜在瓶颈。
EXPLAIN 怎么用才有效
直接在 SELECT 前加 EXPLAIN 即可,例如:
EXPLAIN SELECT * FROM users WHERE name = '张三' AND age > 25 ORDER BY created_at DESC;
注意别只看单条语句——复杂查询要连带子查询、JOIN、UNION 一起分析;推荐配合 FORMAT=JSON 查看更完整的估算信息,比如实际使用的索引长度、是否使用了索引排序等。
图形化工具(如 MySQL Workbench)点“Explain”按钮也行,但得确认它没自动加 LIMIT 或改写 SQL,否则执行计划失真。
type 列是性能判断的第一道关卡
它反映 MySQL 访问表的方式,从优到劣常见顺序是:const → eq_ref → ref → range → index → ALL。重点关注后三项:
- range:走了索引,但做了范围扫描(如 age BETWEEN 18 AND 30),合理;
- index:全索引扫描,比全表扫描略好,但本质仍是遍历整个索引树,说明可能缺更精准的索引;
- ALL:全表扫描,必须优化——检查是否有可用索引、WHERE 条件是否触发了索引失效(如对字段做函数操作、隐式类型转换)。
特别提醒:ref 不代表一定快,如果对应索引区分度极低(比如性别字段建了索引),实际扫描行数可能接近全表。
key 和 rows 联合看,才能识破“假走索引”
key 显示实际用到的索引名,但光有 key ≠ 高效。一定要对照 rows(预估扫描行数):
- key 显示用了 idx_name_age,但 rows 是 50 万——说明虽然走了索引,但筛选效果差,可能因为条件没覆盖最左前缀,或范围查询截断了后续字段使用;
- key 为 NULL,rows 却很小——可能是走了主键聚簇索引(即没有额外二级索引可用),也可能是优化器认为全表扫描反而更快(小表或缓存命中高);
- key 正确但 rows 偏大,优先检查统计信息是否过期:ANALYZE TABLE table_name; 可强制更新。
Extra 字段藏着真实瓶颈线索
这是最容易被忽略、却最实用的部分:
- Using filesort:需要额外排序,未利用索引完成 ORDER BY。解决方法是让 ORDER BY 字段包含在联合索引的尾部,且 WHERE 条件能命中该索引前缀;
- Using temporary:创建了临时表,常见于 GROUP BY、DISTINCT、某些 JOIN 场景。若数据量大,会严重拖慢性能;
- Using index:好消息,表示走了覆盖索引,无需回表;
- Using where; Using index:更理想,既覆盖索引,又在引擎层完成了 WHERE 过滤;
- Using join buffer:关联查询时无法走索引,退化为块嵌套循环(BNL),应优先给被驱动表的关联字段加索引。










