LIKE '%abc'一定不走B+树索引,因B+树按字典序存储且仅支持左前缀匹配,无法定位“结尾为abc”的扫描起点,只能全表扫描,type=ALL、key=NULL;FORCE INDEX和ANALYZE TABLE均无效,属索引结构硬限制。

LIKE '%abc' 为什么一定不走 B+ 树索引
因为 B+ 树索引按字段值字典序存储,查找必须从一个确定的前缀开始向右遍历。LIKE 'abc%' 能定位到第一个 ≥ 'abc' 的记录,然后范围扫描;而 LIKE '%abc' 要匹配“结尾为 abc”的字符串,索引里没存反向顺序,根本找不到扫描起点——只能全表扫。执行计划中 type 一定是 ALL,key 一定是 NULL。
FORCE INDEX 或 ANALYZE TABLE 能解决吗
不能。这不是统计信息不准或优化器选错的问题,是索引结构本身的硬限制:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
-
FORCE INDEX强制指定索引后,MySQL 仍会报错或退化为全表扫描(5.7+ 版本直接拒绝) -
ANALYZE TABLE只影响优化器对成本的估算,但无法让 B+ 树支持后缀定位 - 复合索引如
(status, name)对name LIKE '%abc'完全无效——该字段在索引中不可用
哪些替代方案真能绕过这个限制
真正可行的只有三条路,取决于字段长度和查询强度:
- 短字段(用户名、编码等):加冗余列
name_reversed,用ALTER TABLE t ADD COLUMN name_reversed VARCHAR(255) GENERATED ALWAYS AS (REVERSE(name)) STORED,再建普通索引,查时写成WHERE name_reversed LIKE REVERSE('abc') + '%' - 中长文本(标题、简介):建
FULLTEXT索引,改用MATCH(name) AGAINST('abc' IN NATURAL LANGUAGE MODE)——注意ft_min_word_len默认是 4,搜“go” 就查不到 - 高并发/分词/高亮需求:把 MySQL 当原始数据源,用
Elasticsearch或Meilisearch承担模糊查询
最容易被忽略的失效点
即使你上了 FULLTEXT,只要 AGAINST 里的词长度小于 ft_min_word_len,或者字段被 UPPER() 包裹、collation 不一致、连接时未声明 charset,索引就静默失效。它看起来像“偶尔不生效”,其实是必然不触发——真正的瓶颈从来不在 LIKE 本身,而在字符处理链路上的任意一环。

















