你给表加了索引,EXPLAIN 也看了,type 显示 ALL,执行计划里 key 是 NULL——明明建了索引,查询还是慢得像在等泡面煮熟。这不是玄学,是真实发生的日常。
一、WHERE 条件用了函数或表达式
比如字段是 create_time,你写:
SELECT * FROM orders WHERE DATE(create_time) = '2024-06-15';MySQL 无法直接用索引扫描 DATE() 的结果,索引就废了。改成:SELECT * FROM orders WHERE create_time >= '2024-06-15 00:00:00' AND create_time < '2024-06-16 00:00:00';索引立马活过来。二、LIKE 开头带 %,比如 %abc
这个最典型:
SELECT * FROM users WHERE name LIKE '%三';左边通配,B+树没法从根往下找,只能全表扫。如果真要模糊查后缀,考虑倒序存字段+前缀索引,或者上全文索引。三、类型不匹配,隐式转换悄悄搞鬼
user_id 是 BIGINT,但你传了个字符串:
SELECT * FROM users WHERE user_id = '12345';MySQL 会把索引字段转成字符串比对,索引失效。换成不带引号的数字:SELECT * FROM users WHERE user_id = 12345;再看 EXPLAIN,key 就亮了。四、联合索引没按最左前缀用
你建了 (status, city, age),但只查:
SELECT * FROM users WHERE city = '杭州' AND age > 25;没带 status,索引直接跳过。要么补上 status 条件,要么调整索引顺序,把高频过滤字段放最左。五、数据量太小,优化器觉得没必要用
一张表才 200 行,就算有索引,MySQL 也可能选全表扫描——因为一次磁盘 IO 比走索引树还快。别慌,这不是 bug,是它算得比你还精。上线前多压测,用真实量级验证。
遇到索引不生效,别第一反应删索引重来。打开 EXPLAIN,盯住 key、rows、type 这三列,一条条对照,多数时候,问题就藏在那行 SQL 的小细节里。