like '%abc'一定触发全表扫描,因b+树索引仅支持左前缀匹配,无法定位“结尾为abc”的起始位置;只有like 'abc%'、like 'ab_c'等含确定左前缀的写法才能走索引。

LIKE '%abc' 为什么一定触发全表扫描
因为 B+ 树索引是按字符串字典序从左到右组织的,LIKE '%abc' 要求匹配“末尾为 abc”的所有值,数据库无法从索引中定位起始位置——没有左前缀约束,就等于放弃索引的有序性优势。哪怕 name 字段上有完整索引,EXPLAIN 也会显示 type: ALL 或 key: NULL。
哪些 LIKE 写法能真正走索引
只有满足「确定左前缀」的模式才可能利用 B+ 树索引做范围扫描:
-
LIKE 'abc%'✅ 可走索引:从字典序 'abc' 开始向右遍历 -
LIKE 'ab_c'✅ 可走索引:_是单字符通配,不破坏前缀连续性 -
LIKE 'abc\%'✅(配合ESCAPE '\'):转义后等价于固定前缀 -
LIKE '%abc%'❌ 不走索引:前后都无确定边界 -
LIKE 'ab%c'❌ 索引仅加速到'ab',后续仍需逐行字符串匹配
MySQL 8.0+ 反向索引是少数可行的兜底方案
如果业务强依赖后缀匹配(如查邮箱域名、文件扩展名),可借助函数索引绕过限制:
CREATE INDEX idx_name_rev ON users((REVERSE(name)));<br>SELECT * FROM users WHERE REVERSE(name) LIKE REVERSE('gmail.com') || '%';
注意:REVERSE() 必须出现在 WHERE 左侧,且右侧不能包裹在函数里;低版本 MySQL 需手动加 name_rev 列并建普通索引。
容易被忽略的隐式失效点
即使写成 LIKE 'abc%',索引也可能不生效:
- 字段用了
LOWER(name)或CONCAT('%', @kw)—— 函数调用直接让索引失效 - 字段 collation 是
utf8mb4_bin,但查询条件含大小写混用,导致实际命中率低,优化器主动弃用索引 - 前缀太短(如
LIKE 'A%')且该值占比超 20%,优化器判断走索引反而更慢,直接选全表扫描 - 联合索引为
(status, name),但查询只写了WHERE name LIKE 'abc%'—— 违反最左前缀原则
真正关键的不是“有没有索引”,而是执行计划里 rows 是否显著小于表总行数、key 是否非空、type 是否为 range。











