EXPLAIN能揭示SQL执行慢的根本原因,因为它不执行查询而只返回MySQL的执行计划,通过type(如ALL表示全表扫描)、key(实际使用索引)、rows(预估扫描行数)、Extra(如Using filesort或Using temporary)等关键字段,精准定位性能瓶颈所在。

EXPLAIN 为什么能看执行时间长的原因
执行慢不是因为 SQL 写得“丑”,而是数据库没按你预期的方式去查数据。EXPLAIN 不运行查询,只返回它打算怎么执行——比如走不走索引、会不会全表扫描、要不要临时表、是否用到排序缓冲区。这些信息直接对应耗时大头。
真正要注意的不是“有没有 EXPLAIN”,而是它输出里几个关键字段:type(访问类型)、key(实际用的索引)、rows(预估扫描行数)、Extra(额外操作,比如 Using filesort 或 Using temporary)。
MySQL 中怎么正确加 EXPLAIN 查看执行计划
在原查询前加 EXPLAIN 即可,但别漏掉 WHERE 条件和 LIMIT(它们极大影响执行路径)。如果查询带变量或参数,建议先替换成具体值再 EXPLAIN,否则优化器可能无法准确估算。
EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND status = 'paid';- 避免
EXPLAIN SELECT * FROM orders WHERE user_id = ?;(? 是占位符,MySQL 5.7+ 可能退化为全表扫描预估) - 对复杂查询(含 JOIN、子查询),
EXPLAIN FORMAT=JSON能看到嵌套结构和成本估算,比传统格式更准
看懂 EXPLAIN 输出里最危险的几行
type 是第一眼要扫的:出现 ALL 表示全表扫描,index 是全索引扫描(仍慢),理想是 ref、range 或 const;key 为空说明根本没走索引;rows 如果远大于实际结果行数(比如查 10 行却显示 rows=85000),说明索引失效或统计信息过期。
Extra 里出现这些基本等于性能红灯:
-
Using filesort:ORDER BY 没走索引,要额外排序 -
Using temporary:GROUP BY 或 DISTINCT 触发临时表,内存/磁盘开销大 -
Using join buffer:JOIN 没走索引,靠缓存硬扛,小表还行,大表很伤
EXPLAIN 看完之后该做什么
别只盯着 EXPLAIN 发呆——它只告诉你“计划”,不告诉你“怎么改”。下一步动作很明确:
- 如果
key是空,检查 WHERE 字段是否有索引,注意联合索引顺序(WHERE a = ? AND b = ?要建(a,b),不是(b,a)) - 如果
rows夸张偏高,运行ANALYZE TABLE table_name;更新统计信息(尤其在大批量 INSERT/DELETE 后) - 如果
Extra有Using filesort,且排序字段固定,考虑把排序字段加入联合索引末尾(如INDEX (user_id, created_at)支持WHERE user_id = ? ORDER BY created_at)
真实场景里,EXPLAIN 往往只是起点,真正卡点常藏在索引设计与查询条件的微妙错位中——比如隐式类型转换让索引失效,或者函数包裹字段(WHERE YEAR(create_time) = 2024)导致无法走索引,这些都不会直接写在 EXPLAIN 里,但会彻底改变 type 和 key 的表现。


















