LIKE 'abc%'能走索引,因B+树按字典序排序,该模式等价于name >= 'abc' AND name < 'abd',可定位起始点并range扫描;而'%abc'和'%abc%'无法定位起点,必须全表扫描。

LIKE 'abc%' 为什么能走索引
B+ 树索引是按字典序严格排序存储的,LIKE 'abc%' 实际等价于范围查询 name >= 'abc' AND name 。优化器能直接定位到索引中以 <code>'abc' 开头的第一条记录,然后向右顺序扫描所有匹配项——这是 B+ 树天然支持的操作。
关键前提是:模式必须是“固定前缀 + 右模糊”,且不能对字段做任何函数处理(比如 UPPER(name) LIKE 'ABC%' 会彻底失效索引)。
- 字段类型为
VARCHAR或TEXT时,要确认索引长度足够,例如建索引时写了INDEX(name(191)),而实际匹配内容超长,也会退化为全表扫描 - 排序规则(如
utf8mb4_0900_as_cs)会影响大小写行为,但不改变能否走索引的判断逻辑 -
EXPLAIN中type应为range或ref,key字段显示索引名,才是真生效
LIKE '%abc' 为什么完全不走索引
因为 B+ 树无法反向跳转或从中间开始扫描。LIKE '%abc' 要求找出所有以 'abc' 结尾的值,而这些值在索引里是分散存储的——比如 'xabc'、'yzabc'、'123abc' 在字典序中相距很远,没有连续物理位置可利用。
此时优化器别无选择,只能扫完整个索引(或更糟:全表扫描),EXPLAIN 显示 type=ALL 且 key=NULL 就是典型信号。
- 哪怕该字段有单列索引,甚至联合索引最左字段就是它,只要模式是前导
%,索引就形同虚设 -
LIKE '%abc%'同样无效,中缀匹配同样破坏有序性,B+ 树无法加速 - 不要尝试用
CONCAT('%', ?)拼接参数来“绕过”,这等于把字段丢进表达式,索引照样失效
联合索引下 LIKE 的匹配边界在哪
联合索引 idx_name_age_dept(name, age, dept) 中,LIKE 只能作用于最左连续字段部分。例如:
-
WHERE name LIKE 'zhang%' AND age = 25→ 可用索引,name是最左字段且满足前缀匹配 -
WHERE age = 25 AND name LIKE 'zhang%'→ 同样可用,优化器会自动调整条件顺序 -
WHERE age = 25 AND dept = 'tech'→ 完全不走该索引,跳过了最左字段name -
WHERE name = 'zhang' AND age > 20 AND dept LIKE '%dev'→dept上的LIKE不生效,且age > 20是范围查询,会截断后续字段的索引使用,dept实际无法参与索引查找
后缀匹配真的一点办法都没有?
普通 B+ 树索引确实无解,但不是完全没路可走:
- 全文索引(
FULLTEXT)适用于自然语言关键词召回,比如搜“优化”命中含“数据库优化”的正文,但它不解决“字段值以‘优化’结尾”这类精确后缀问题 - 倒排索引类方案(如 Elasticsearch)或 MySQL 8.0+ 的
REGEXP+ 函数索引(需谨慎评估性能)可作为补充,但代价高、运维重 - 业务层改写:如果场景固定(如邮箱域名查询),可额外存一个
domain字段并建索引,把email LIKE '%@gmail.com'转为domain = 'gmail.com'
真正容易被忽略的是:很多所谓“模糊需求”其实并不需要后缀匹配,而是用户输入习惯导致的误判——先确认是否真的必须查结尾,还是只是没意识到前缀匹配+业务引导就能覆盖 90% 场景。


















