key为NULL不表示无索引,而是优化器跳过索引;需结合type、rows、possible_keys、Extra等字段判断原因,常见于隐式转换、函数使用、联合索引未满足最左前缀等场景。

EXPLAIN 中 key 为 NULL 不代表索引不存在,而是优化器主动跳过了所有可用索引——你要查的不是“有没有索引”,而是“为什么不用”。
先确认是不是真没走索引
只看 key 列为 NULL 还不够,必须结合其他字段交叉验证:
-
type是ALL或index,且rows接近表总行数 → 基本确定全表扫描 -
possible_keys有值但key为NULL→ 索引存在,但被弃用 -
rows很小(比如表只有 10 行),key仍为NULL→ 优化器认为没必要走索引,属正常行为 -
Extra出现Using where但没Using index→ 条件过滤发生在引擎层之后,索引未覆盖查询路径
检查 JOIN 场景下的被驱动表索引
多表 JOIN 时,key 为 NULL 最常出在被驱动表(即非第一张表)的 ON 字段上:
- 被驱动表的
ON字段没建索引 → 立即补索引,优先单列索引而非依赖联合索引 -
ON左右字段类型不一致(如INTvsVARCHAR)→ 触发隐式转换,索引失效 -
ON中对字段用了函数或表达式(如ON a.id = CAST(b.ref_id AS SIGNED))→ 索引无法匹配 - 联合索引未满足最左前缀(如索引是
(status, created_at),但ON只用了created_at)→ 不会命中
排查 WHERE 条件导致的索引失效
WHERE 子句写法直接影响优化器是否启用索引:
- 对索引字段使用函数:
WHERE DATE(create_time) = '2026-08-01'→ 改成WHERE create_time >= '2026-08-01' AND create_time - 使用
!=、NOT IN、OR(且各分支字段无共享索引)→ 尝试拆成UNION或重写逻辑 - 模糊查询带前导
%:LIKE '%abc'→ 无法走索引;LIKE 'abc%'可以 -
IS NULL查询返回key=NULL→ 不一定是索引问题,先查该列NULL占比;若超 20%,优化器可能真觉得全扫更快
别忽略统计信息和数据分布
即使语法、索引、类型都正确,key 仍为 NULL,大概率是优化器“算错了”:
- 执行
ANALYZE TABLE <code>table_name更新统计信息,尤其在大批量写入后 - 用
SHOW INDEX FROM <code>table_name检查Cardinality是否明显偏低(比如远小于实际唯一值数量) - 小表(
rows < 100)或高重复值字段(如status只有 3 个值),优化器天然倾向全表扫描 - 临时加
FORCE INDEX(<code>index_name) 测试:如果rows显著下降、Extra出现Using index condition,说明原问题在成本估算失准,而非索引设计错误
真正棘手的不是 key=NULL 本身,而是它背后混杂了语法、结构、统计、成本四层判断逻辑。每次看到这个现象,得像调试代码一样逐层排除:先看执行计划全貌,再盯住具体表和字段,最后动手改 SQL 或索引——而不是一上来就重建索引或调优配置。


















