like 'abc%'能走索引,因b+树按字典序排序,该模式等价于name >= 'abc' and name
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'→ 完全不走该索引,跳过了最左字段nameWHERE 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% 场景。












