like '%abc'导致索引失效,因b+树无法利用有序性;对索引列用函数、隐式类型转换、联合索引不满足最左前缀原则均会引发索引失效。

LIKE 查询以 % 开头导致索引失效
当 WHERE 条件中使用 LIKE 且左侧通配符为 %(如 LIKE '%abc'),MySQL 无法利用 B+ 树索引的有序性进行范围查找,只能全表扫描。
- ✅ 正确用法:
LIKE 'abc%'可走索引(最左前缀匹配) - ❌ 错误写法:
LIKE '%abc'或LIKE '%abc%'基本不走索引(除非覆盖索引 + 优化器强行选中) - ⚠️ 注意:
LIKE是否走索引还取决于字段是否为TEXT类型、是否启用了fulltext索引,普通 B+ 树索引对此无能为力
对索引列做函数或运算操作
在 WHERE 子句中对已建索引的列执行函数调用(如 UPPER()、DATE())或数学运算(如 col + 1 = 10),会导致索引列无法直接比对,优化器放弃使用索引。
- ❌
WHERE UPPER(name) = 'TOM'→name索引失效 - ✅ 改为:确保查询条件与索引列原始形式一致,比如存入时统一小写,查时也用小写
WHERE name = 'tom' - ❌
WHERE create_time + INTERVAL 1 DAY > NOW()→create_time索引不生效 - ✅ 改为:把计算移到右侧,如
WHERE create_time > DATE_SUB(NOW(), INTERVAL 1 DAY)
隐式类型转换引发索引失效
当查询条件中字符串与数字比较(如 WHERE user_id = '123',而 user_id 是 INT 类型),MySQL 会将列转为字符串再比对,破坏索引的二分查找能力。
- ❌
WHERE user_id = '123'(user_id是INT)→ 触发隐式转换,索引可能失效 - ✅ 应该写成:
WHERE user_id = 123,保持类型严格一致 - ⚠️ 同样适用于
VARCHAR字段存数字但未加引号:WHERE phone = 13812345678(phone是VARCHAR)也会触发转换 - ? 查看执行计划时注意
type是否为ALL或index,以及Extra列是否出现Using where; Using index或Using filesort
联合索引未满足最左前缀原则
联合索引 (a, b, c) 的有效使用必须从最左列开始连续匹配。跳过左侧列(如只查 b 或 c),或中间断开(如查 a 和 c 但不查 b),都会导致后续列无法命中索引。
立即学习“Java免费学习笔记(深入)”;
- ✅ 有效:
WHERE a = 1、WHERE a = 1 AND b = 2、WHERE a = 1 AND b = 2 AND c = 3 - ❌ 无效:
WHERE b = 2、WHERE c = 3、WHERE a = 1 AND c = 3(缺少b) - ⚠️ 特殊情况:
WHERE a > 1 AND b = 2中,a是范围查询,b仍可走索引;但WHERE a > 1 AND b > 2 AND c = 3中,c就无法利用索引了
EXPLAIN SELECT * FROM user WHERE name = 'Tom' AND age > 25 AND city = 'Beijing';
如果联合索引是 (name, age, city),这条语句能用上全部三列;但如果索引是 (name, city, age),则 city 实际无法生效——因为 age 在 city 后面且是范围查询,city 列索引就“断”了。
真正容易被忽略的是:索引列顺序不是按查询频率排的,而是按「过滤性 + 查询模式」综合设计的;线上慢查往往不是没建索引,而是索引列顺序和实际 SQL 不匹配。










