explain关键看type、key、rows、extra四列:type差为all(全表扫描),key空表示未用索引,rows是预估扫描行数,extra含using filesort/temporary为性能红灯。

EXPLAIN 输出字段怎么看
执行 EXPLAIN SELECT ... 后,关键要看 type、key、rows、Extra 这四列:
-
type值从好到差一般是:const≈eq_ref>ref>range>index>ALL;出现ALL说明全表扫描,大概率缺索引 -
key为空表示没走索引;即使非空,也要结合key_len看是否用了联合索引的最左前缀 -
rows是 MySQL 预估扫描行数,不是结果行数;比实际数据量大很多时,统计信息可能过期,可运行ANALYZE TABLE -
Extra出现Using filesort或Using temporary是性能红灯,通常意味着排序或分组没走索引
哪些 SQL 必须加 EXPLAIN
不是所有语句都值得分析,优先盯住这几类:
- 响应明显变慢的线上查询(尤其是
SELECT带ORDER BY/GROUP BY/ 多表JOIN) - 写入频繁但查询也多的表上的
WHERE条件,比如WHERE status = ? AND created_at > ? - 任何在慢日志里出现的语句(
slow_query_log开启后抓出来的) - 用到了函数或计算的条件,如
WHERE YEAR(create_time) = 2024—— 这种几乎必然无法用索引
EXPLAIN 的常见误判和陷阱
EXPLAIN 只是预估执行计划,不真正执行 SQL,所以有几处容易误导:
- 不会反映实际锁等待、MVCC 版本链遍历开销,高并发下
rows=100的语句可能卡住几秒 - 对
IN子查询支持有限,EXPLAIN可能显示DEPENDENT SUBQUERY却不告诉你子查询被反复执行多少次 - MySQL 8.0+ 引入了
FORMAT=JSON模式(EXPLAIN FORMAT=JSON SELECT ...),能看更细的cost_info和used_columns,但默认文本模式看不到 - 如果语句含用户变量(如
@var := @var + 1),EXPLAIN会直接报错或返回空,得先剥离逻辑再分析
配合 SHOW PROFILE 定位真实瓶颈
EXPLAIN 告诉你“怎么走”,但不告诉你“哪一步最耗时”。开启 profiling 后可补全这一环:
- 先执行
SET profiling = 1 - 再跑你的 SQL
- 然后查
SHOW PROFILES找 query_id,再用SHOW PROFILE FOR QUERY N看各阶段耗时(如Sending data高说明结果集大或网络慢,Creating sort index高说明排序没走索引) - 注意:profiling 在 MySQL 8.0 中已被标记为 deprecated,生产环境建议用
performance_schema替代,但开发调试仍够用
EXPLAIN 只是起点。真正难的是判断「为什么没走索引」——是隐式类型转换?是索引失效于范围查询后的字段?还是优化器基于错误统计选了次优路径?这些往往要结合 SHOW CREATE TABLE、SHOW INDEX 和真实数据分布一起看。










