mysql索引不生效怎么排查_mysql执行计划分析方法

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

直接看
EXPLAIN
key
列是否为
NULL

索引有没有生效,第一眼就看

EXPLAIN
输出里的
key
这一列:如果是
NULL
,说明没走索引;否则就是用了某个索引。别信“我建了索引它就应该用”,MySQL 优化器会根据统计信息、数据分布、查询写法等综合判断——它可能觉得全表扫描更快。

执行前加
EXPLAIN
即可,例如:
EXPLAIN SELECT * FROM orders WHERE create_time > '2025-01-01';
重点关注
type
字段:
ALL
是全表扫描,
range
ref
才算有效利用索引
possible_keys
显示“可能用”,
key
才是“实际用”,两者不一致很常见

日期字段上用了
YEAR()
DATE()
等函数?立刻失效

对索引列做任何函数操作,MySQL 就无法用 B+ 树快速定位,只能扫全表。比如

YEAR(create_time) = 2025
,哪怕
create_time
有索引也白搭。

✅ 正确写法(能走索引):
WHERE create_time >= '2025-01-01' AND create_time < '2026-01-01'
❌ 典型失效写法:
WHERE YEAR(create_time) = 2025
WHERE DATE(create_time) = '2025-12-30'
如果必须按年/月查,考虑用生成列 + 函数索引(MySQL 5.7+ 支持虚拟列,8.0+ 支持函数索引)

联合索引没按最左前缀用?右边字段全作废

比如你建了

(sn, name, age)
联合索引,那只有以
sn
开头的查询才能触发它。单独查
name
age
,或者
name AND age
,索引完全不参与。

✅ 可用索引:
WHERE sn = 'cn001'
WHERE sn = 'cn001' AND name = '张三'
WHERE sn = 'cn001' AND age > 18
❌ 不可用:
WHERE name = '张三'
WHERE name = '张三' AND age > 18
WHERE age > 18
注意:范围查询(如
>
BETWEEN
)之后的字段,索引也无法继续使用,比如
WHERE sn = 'x' AND name > 'a' AND age = 25
中,
age
就不会走索引

字符串字段没加引号?类型隐式转换让索引沉默

当索引列是

VARCHAR
,而你在
WHERE
里写了数字(比如
WHERE sn = 123
),MySQL 会把每行
sn
值转成数字再比——这等于对索引列做了函数操作,索引直接失效。

✅ 正确:
WHERE sn = 'cn001'
(字符串值必须加单引号)
❌ 错误:
WHERE sn = cn001
(未加引号,被当列名或变量)、
WHERE sn = 123
(类型不匹配)
SHOW WARNINGS
可看到隐式转换提示,比如
Warning | 1292 | Truncated incorrect DOUBLE value: 'cn001'

真正卡住人的,往往不是“没建索引”,而是“建了但根本没进优化器的法眼”——比如日期函数包裹、联合索引跳过首列、字符串漏引号。这些地方不翻

EXPLAIN
,光看 SQL 写得“顺”,很容易误判。

相关推荐