explain中key和type字段最直接判断索引是否生效:key为null或type为all表示未走索引;const/ref/range属正常走索引;需警惕函数操作、隐式转换、or跨索引等导致失效的情况。

EXPLAIN 输出里看 key 和 type 字段最直接
查 SQL 有没有走索引,不能只看执行快不快,得看 MySQL 实际用没用上索引。核心就盯两个字段:key 显示实际使用的索引名,type 表示连接类型——const、ref、range 算正常走索引;ALL 或 index 基本等于全表扫描。
-
key为NULL:没用任何索引(哪怕表上有) -
type是ALL:MySQL 扫了整张表,索引失效常见信号 -
key有值但rows很大:可能走了索引,但筛选效果差,比如前导列没用上
WHERE 条件写法不对,EXPLAIN 会骗你
EXPLAIN 只告诉你“计划怎么走”,不是“一定这么走”。很多看似能走索引的写法,在实际数据分布或表达式下会被优化器放弃。
- 对索引字段做函数操作:
WHERE YEAR(create_time) = 2024→create_time索引失效 - 隐式类型转换:
WHERE user_id = '123'(user_id是INT)→ 可能触发全表扫描 - 使用
OR连接非同一索引字段:WHERE a = 1 OR b = 2,且a、b没有联合索引 → 很可能退化为ALL
加 FORCE INDEX 能绕过优化器误判,但要慎用
当 EXPLAIN 显示没走索引,但你知道数据特征适合走某个索引(比如小结果集 + 高选择性字段),可以用 FORCE INDEX 强制指定。
- 语法:
SELECT * FROM orders FORCE INDEX (idx_user_status) WHERE user_id = 123 AND status = 'paid'; - 风险:MySQL 版本升级、数据量变化后,强制索引可能比优化器选的更慢
- 只建议在确认优化器判断明显错误、且已用
EXPLAIN FORMAT=JSON查过used_columns和filtered后临时使用
复合索引顺序和查询条件顺序不严格匹配,但前导列必须覆盖
联合索引 (a, b, c) 不要求 WHERE 中字段顺序和它完全一致,但必须从左到右连续使用前导列。
- ✅
WHERE a = 1 AND b = 2:走索引,用到前两列 - ✅
WHERE a = 1 AND b > 10 AND c = 5:b是范围查询,c仍可用(索引跳过) - ❌
WHERE b = 2 AND c = 5:没用a,索引完全失效 - ⚠️
WHERE a = 1 AND c = 5:b缺失,c无法命中,只用到a
索引是否生效,最终取决于优化器对成本的估算,而不仅仅是语句写法。同一个 EXPLAIN 结果,在不同数据量、不同 MySQL 版本下可能行为不一致。别只信一次输出,要结合 SHOW INDEX、真实 SELECT 的执行时间、以及 Handler<em>read</em>* 状态变量交叉验证。










