EXPLAIN的type字段表示MySQL访问表数据的方式,直接反映查询效率,从优到劣依次为system>const>eq_ref>ref>range>index>ALL。

EXPLAIN 的 type 字段到底在说啥
type 是 EXPLAIN 输出里最直白的性能信号灯——它告诉你 MySQL 用什么方式去查这张表。值越靠左,效率通常越高:system ≈ const ≈ eq_ref > ref > range > index > ALL。其中 ALL 就是全表扫描,绝大多数索引失效场景最终都会落到这个值上。
它不直接说“索引没用”,而是用访问类型暴露底层行为:比如你加了 WHERE status = ? 却看到 type: ALL,那基本可以断定索引根本没参与查询路径。
哪些操作会让 type 变成 ALL 或 index
不是加了索引就万事大吉。以下操作常见于真实业务 SQL,会直接导致优化器放弃走索引,退化为全表或全索引扫描:
- 对索引列做函数操作:
WHERE YEAR(create_time) = 2024→ 索引失效,type变ALL - 隐式类型转换:
WHERE user_id = '123'(user_id是INT)→ 字符串转数字可能触发全表扫 - 使用
!=或(尤其在非空字段上)→ 优化器常拒用索引,type降为ALL - 前导通配符模糊匹配:
WHERE name LIKE '%abc'→ 无法利用 B+ 树前缀特性,type为ALL - 联合索引未用最左前缀:
INDEX(a,b,c),但只查WHERE b = 1 AND c = 2→type很可能还是ALL
type 显示 index 就算用了索引?不一定
type: index 表示 MySQL 扫描了整个索引树(而不是数据行),听起来比 ALL 好,但实际未必。如果索引本身很宽(比如包含多个 VARCHAR(500) 字段),或者索引大小远超数据行,index 扫描可能比 ALL 更慢。
关键看 key 和 key_len 列是否符合预期:
-
key为空 → 没走任何索引,type: index实际是覆盖主键索引的全扫描(即聚簇索引全扫) -
key_len远小于你预期的索引长度(比如联合索引该用 30 字节却只显示 4)→ 只命中了部分前缀列 - 配合
Extra列看:Using index表示覆盖索引,快;Using where; Using index表示仍需回表过滤,慢
用 EXPLAIN FORMAT=TREE 辅助验证
MySQL 8.0+ 支持树形执行计划,比传统表格更清楚地展示嵌套操作和索引选择逻辑。例如:
EXPLAIN FORMAT=TREE SELECT * FROM orders WHERE user_id = 123 AND status IN ('paid', 'shipped');
它会明确标出哪一步用了哪个索引、是否下推条件、有没有物化临时表。当 type 看着可疑但又不确定原因时,优先跑这个命令。
注意:FORMAT=TREE 不显示 key_len 和 rows,得和传统 EXPLAIN 配合看;另外它对子查询、UNION 的展开更直观,能帮你发现“表面走索引,实则外层驱动内层全扫”的陷阱。
真正难的不是看懂 type,而是把 type 和你的 WHERE 条件、索引定义、表统计信息三者对齐。有时候 ANALYZE TABLE 一下,type 就从 ALL 变 ref 了——因为优化器终于“看清”了数据分布。











