EXPLAIN展示的是MySQL优化器重排后的执行逻辑,而非SQL文本顺序;id相同按上下顺序执行,id越大越先执行;type列(如const、ref、ALL)直接决定I/O性能,Extra和SHOW WARNINGS则揭示优化器真实改写行为与潜在瓶颈。

直接说结论:用 EXPLAIN 看执行计划,不是“看SQL怎么写”,而是看MySQL优化器最终决定怎么查——它可能重排表顺序、改写子查询、跳过某些条件,甚至把 IN 拆成多个等值判断。
为什么 EXPLAIN 返回的不是你写的 SQL 顺序?
MySQL优化器会基于统计信息(如索引基数、行数估算)重排执行顺序,EXPLAIN 显示的就是这个重排后的逻辑。比如你写 SELECT * FROM a JOIN b ON a.id = b.a_id JOIN c ON b.id = c.b_id,但 EXPLAIN 中 table 列的顺序可能是 c、b、a——说明优化器认为先查 c 效率更高。
-
id相同:按EXPLAIN输出的上下顺序执行(非 SQL 文本顺序) -
id不同:数值越大越先执行(注意不是“越小越先”) - 如果出现
derived或union result,对应行的id为NULL,表示这是中间结果,不参与主流程扫描
type 列决定 80% 的性能差异
type 是最该盯紧的一列,它反映单表访问方式,直接关联 I/O 成本。从快到慢依次是:system ≈ const eq_ref ref range index ALL。
-
const:命中主键或唯一索引 + 等值查询(如WHERE id = 123),只查 1 行,最快 -
ref:走了非唯一索引(如普通status字段),但仍是等值匹配;可能返回多行,但能利用索引定位起始点 -
range:索引范围扫描(>、BETWEEN、IN),注意IN后面值太多会退化成ALL -
index:遍历整棵索引树(比ALL快,因为不用回表读数据行,但仍是全量扫索引) -
ALL:必须警惕——没走任何索引,全表扫描,数据量一上去就卡死
Extra 里藏着真实瓶颈线索
Extra 不是补充说明,而是关键行为标记。常见值中,这几个最值得立即干预:
-
Using filesort:排序没走索引,MySQL 自己在内存或磁盘做二次排序——加复合索引覆盖ORDER BY字段 -
Using temporary:创建了临时表,常见于GROUP BY、DISTINCT、含UNION的查询——检查是否能用索引避免分组/去重 -
Using index condition:用了索引下推(ICP),是好事,说明 MySQL 在存储引擎层就过滤了部分数据,减少回表次数 -
Using where:表示 WHERE 条件在服务器层做了过滤(非全部下推到引擎),结合type看——如果type是ALL还带这个,基本等于全表扫完再筛
别忽略 SHOW WARNINGS 里的重写 SQL
执行 EXPLAIN SELECT ... 后,如果看到 “1 warning”,立刻跟一句 SHOW WARNINGS。MySQL 5.7+ 默认会显示优化器改写后的语句,比如:
SELECT * FROM t WHERE id IN (1,2,3) AND status = 'active'
可能被重写为:
SELECT * FROM t WHERE (id = 1 OR id = 2 OR id = 3) AND status = 'active'
这种重写会影响索引选择——原 IN 可能走 range,拆开后可能触发更优的 ref 或 eq_ref。不看 WARNINGS,你就永远不知道优化器到底在想什么。
真正难调的不是语法错误,而是优化器“自作聪明”却没选对路——EXPLAIN 是唯一能把它决策过程摊开来看的工具,但得连 id、type、Extra 和 WARNINGS 四块一起读,缺一不可。











