Skip to content

P30 前模糊索引失效 ​

面试题:LIKE '%关键字'(前模糊)为什么索引失效?怎么优化?

1. 为什么前模糊索引失效 ​

B+ 树索引是按从左到右有序组织的。LIKE 'abc%' 能用索引,因为可以定位到以 abc 开头的区间;

而 LIKE '%abc'、LIKE '%abc%' 的前置部分不确定,无法利用索引的顺序性直接定位起点,只能全索引扫描/全表扫描,所以索引失效。

sql
SELECT * FROM t WHERE name LIKE '%张';     -- 前模糊,索引失效
SELECT * FROM t WHERE name LIKE '张%';     -- 后模糊,可走索引

2. 为什么"xxx%"可以走索引 ​

索引键有序排列,LIKE '张%' 相当于范围查询 name >= '张' AND name < '王'(或 > '张' 且 < '张'+1 的范围),B+ 树可以二分定位起点后顺序扫描。

3. 优化方案 ​

① 修改查询方式(业务允许时) ​

  • 把前模糊改成后模糊/等值:name LIKE '张%';
  • 搜索场景尽量用全文检索(Elasticsearch / MySQL FULLTEXT / ngram 分词),而不是 LIKE 前模糊。

② 反转存储 ​

对需要前模糊的字段,存一份反转后的值(如 name_rev = 反序字符串),查 %张 变成查 张%:

text
原值: "张三"   → name_rev: "三张"
查询: LIKE '%张' → 变成 name_rev LIKE '张%' → 走索引

③ 覆盖索引 + 强制扫描优化 ​

前模糊无法避免时,让扫描尽量轻:查询列都在索引里(覆盖索引),减少回表;配合 LIMIT 控制扫描量。

④ 拆表/冗余字段 ​

高频搜索字段单独建表或冗余可检索的正排结构,用 ES 等专门组件。

加分点 ​

  • 追问"LIKE 'abc%def' 能走索引吗":能部分利用——abc% 走索引区间,%def 部分在回表/引擎层过滤;
  • 面试官还可能问"为什么索引能加速排序/范围":因为 B+ 树叶子节点有序链表;
  • 字符集 collation 影响模糊匹配行为,一般不影响"前模糊失效"的结论。

一句话总结 ​

前模糊 LIKE '%x' 无法利用 B+ 树的有序定位,只能全扫描所以索引失效;优化用"改后模糊/等值、反转字段、全文检索、覆盖索引",核心是让查询能落到索引的有序区间上。

基于 VitePress 重建