SQL LIKE 为何以 % 开头会导致索引失效?

B+树索引仅支持左前缀匹配,LIKE '%abc' 因前导%无法利用索引有序性,必须全表扫描;而'john%'、'jo%hn'等开头固定模式仍可走索引。

因为索引(尤其是 B+ 树)依赖字段值的**前缀有序性**来快速定位数据,而 LIKE '%abc' 这类左模糊查询无法利用这个特性,数据库只能全表扫描。

索引结构决定了它只能“从左匹配”

B+ 树索引把字符串按字典序排列,比如 alicebobcarolcharlie

。查找 'ca%' 时,数据库知道所有匹配项一定集中在 ca 开头的连续区间,可以快速跳转;但查 '%lia' 时,aliabliaclia……可能散落在树的任意分支,没法跳转,只能逐行检查。

不是“不支持 LIKE”,而是“不支持前导 %”

以下写法仍可走索引:

  • WHERE name LIKE 'john%' —— 右模糊,符合最左前缀原则
  • WHERE name LIKE 'jo%hn' —— 中间有通配符但开头固定,仍能定位起始范围
  • SELECT id, name FROM user WHERE name LIKE '%abc' —— 若 (name, id) 是联合索引且查询只涉及这两列,可能触发覆盖索引,避免回表(但依然不加速匹配本身)

真要查后缀或含中间匹配,有更合适的方案

单纯靠普通 B+ 树索引解决不了这类问题:

  • 后缀查询(如 name LIKE '%ing'):可考虑倒序存储 + 右模糊,例如存 gninom 再查 gni%
  • 任意位置匹配(如 LIKE '%abc%'):建议用全文索引(FULLTEXT)或专门的搜索引擎(Elasticsearch、Meilisearch)
  • 高频模糊需求:提前构建关键词映射表,或使用 n-gram 分词索引

小提醒:别被执行计划误导

有时 EXPLAIN 显示 key 非空,不代表模糊条件用了索引——可能是覆盖索引生效,或优化器选了其他可用索引(比如主键)。关键看 type 是否为 rangeref,而不是 ALL;再结合 key_len 和实际查询逻辑判断真正生效的部分。