mysql执行计划中key为null是什么意思_mysql索引问题排查

来源:这里教程网 时间:2026-02-28 20:46:49 作者:

key 为 NULL 表示没走索引

MySQL 执行计划(

EXPLAIN
输出)中
key
列为
NULL
,说明优化器最终没有选择任何索引去访问该表,而是走了全表扫描(
type
通常是
ALL
)。这不是“索引不可用”,而是“优化器判断用索引不划算”——可能因为:

查询条件没命中索引最左前缀(比如对复合索引
(a,b,c)
只写了
WHERE b = ?
字段存在隐式类型转换(如
WHERE user_id = '123'
,而
user_id
INT
索引列上用了函数或表达式(如
WHERE UPPER(name) = 'ABC'
统计信息过期,优化器误判行数,认为全表扫描比索引回表更快 查询返回大量数据(例如
SELECT *
+ 高比例匹配),优化器放弃索引+回表的开销

怎么确认是不是索引本身失效了

别急着删重建索引,先验证索引是否真的“能用”。执行

SHOW INDEX FROM table_name
确认索引存在且状态正常;再用
EXPLAIN
检查带索引字段的**最简等值查询**:

EXPLAIN SELECT * FROM users WHERE email = 'a@b.com';

如果这时

key
仍是
NULL
,重点排查:

email
字段是否为
NULL
允许?若允许,且查询条件是
WHERE email = 'x'
,但该列 NULL 值占比极高,优化器可能直接弃用索引
是否在
email
上建的是普通索引,但查询用了
LIKE '%abc'
?这种前导通配符必然无法使用 B+Tree 索引
检查字符集/排序规则是否一致(比如表用
utf8mb4_0900_as_cs
,而连接会话用
utf8mb4_general_ci
),可能导致索引失效

force index 能临时绕过但不该长期依赖

FORCE INDEX
可以强制走某个索引,用于验证“如果走索引,性能到底如何”:

EXPLAIN SELECT * FROM orders FORCE INDEX (idx_status_created) WHERE status = 'paid' AND created_at > '2024-01-01';

但如果

key
原本是
NULL
,而加了
FORCE INDEX
rows
显著下降、
Extra
出现
Using index
Using index condition
,说明问题不在索引缺失,而在优化器成本估算失准。此时更应:

运行
ANALYZE TABLE orders
更新统计信息
检查
innodb_stats_persistent
是否开启,避免统计信息长期不更新
确认
WHERE
条件的选择性——低选择性(如
status IN ('paid','shipped')
占 90% 行)会让索引失去意义

覆盖索引和联合索引顺序很关键

key
不为
NULL
,但
Extra
里出现
Using where; Using index
,说明走了覆盖索引;如果只有
Using where
,大概率发生了回表。这时候即使
key
有值,性能也可能差。

联合索引要按“查询条件(= 或 IN)→ 排序字段 → 查询返回字段”顺序组织,例如
WHERE a = ? AND b > ? ORDER BY c
,理想索引是
(a, b, c)
如果查询里有
SELECT *
,几乎不可能覆盖,除非索引包含所有列(不现实),所以优先考虑只查必要字段
注意
ORDER BY
GROUP BY
的字段顺序必须匹配索引最左前缀,否则即便
key
有值,也会多出
Using filesort
Using temporary

实际调优时,

key
NULL
往往不是孤立现象,它常和
type: ALL
rows
过大、
Extra
出现
Using where
Using temporary
一起出现。盯住这几个字段组合,比单看
key
更能定位根因。

相关推荐