LIKE '%abc'一定不走索引,因B+树仅支持左前缀匹配,无法定位结尾匹配的扫描起点,优化器直接全表扫描,EXPLAIN显示type=ALL、key=NULL。

因为B+树索引无法定位扫描起点,不是配置或写法问题,是数据结构硬限制。
为什么LIKE '%abc'一定不走索引
B+树索引按字段值字典序存储,查找必须从一个确定前缀开始向右遍历。LIKE 'abc%'能定位到第一个 ≥ 'abc' 的记录,然后范围扫描;而LIKE '%abc'要匹配“结尾为 abc”的字符串,索引里没有反向顺序,也没有任何节点能告诉你“从哪儿开始查才可能命中”。优化器看到这种模式,直接放弃索引,执行计划中type一定是ALL,key一定是NULL。
常见错误现象:
- 加了
FORCE INDEX(idx_name)也没用 - 复合索引
(status, name)中,WHERE status = 1 AND name LIKE '%abc'依然只用到status,name部分完全失效 -
EXPLAIN显示Extra: Using where,但没Using index condition
LIKE '%abc%'和REGEXP 'abc$'一样不走索引
两者都属于“非前缀匹配”,MySQL的B+树不支持后缀或中缀定位。哪怕你把name字段建得再细(比如INDEX(name(10))),只要模式以%开头,就毫无意义。
注意:REGEXP 'abc$'看起来像后缀,但它底层是逐行调用正则引擎匹配,和LIKE一样绕不开全表扫描。别指望改写成正则就能“唤醒”索引。
使用场景差异:
MySQL 数据库管理技能,能够通过自然语言查询和管理数据库,支持 SELECT/INSERT/UPDATE/DELETE、表管理、备份恢复等操作。当用户提及 MySQL、数据库查询、建表或数据备份时使用此技能。
-
LIKE 'abc%'→ 可走索引,等价于name >= 'abc' AND name -
LIKE 'ab%c'→ 不走索引,中间有通配符,边界无法确定 -
LIKE 'a%b%c'→ 同样失效,B+树不支持跳跃式前缀
字符集和排序规则会让问题更隐蔽
即使你写了LIKE '张%',也可能不走索引——根源常在隐式转换:
- 表列用
utf8mb4,但客户端连接用latin1→ 查询时MySQL自动CAST列值,索引失效 - 排序规则是
utf8mb4_general_ci,遇到“張”和“张”简繁差异,可能无法落在同一索引分支 - 建表没显式指定
COLLATE,依赖服务器默认值 → 开发/测试/生产环境行为不一致
检查方法:
-
SHOW CREATE TABLE users;确认列定义含CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci -
SHOW VARIABLES LIKE 'character_set%';和SHOW VARIABLES LIKE 'collation%';,确保client/connection/results三者一致
真正可行的绕过方式只有两类
硬扛LIKE '%keyword%'在万级以上数据量就会卡死。别试函数索引+REVERSE(),MySQL 8.0+虽支持,但REVERSE(name) LIKE REVERSE('abc') + '%'实际仍是全索引扫描,排序丢失,性能无本质改善。
根据字段长度和业务需求选路:
- 短字段(用户名、编码、ID):加冗余列
name_reversed,建普通索引,查时写WHERE name_reversed LIKE REVERSE('abc') + '%' - 中长文本(标题、简介):建
FULLTEXT索引,改用MATCH(name) AGAINST('keyword' IN NATURAL LANGUAGE MODE);注意ft_min_word_len默认是4,搜“go”必须调低并重建索引 - 高频模糊查且需分词/高亮/高并发:引入
Elasticsearch或Meilisearch,MySQL只作原始数据源
最容易被忽略的一点:即使加了FULLTEXT索引,AGAINST里的词若少于ft_min_word_len,或者字段上有函数包裹、collation不一致,索引就只是摆设——它看起来像偶然失效,其实是必然。

















