直接看 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 写得“顺”,很容易误判。
