like查询慢的本质是索引失效,尤其是'%abc'类左通配导致全表扫描;仅'abc%'等左前缀匹配能走索引,其他场景需用全文索引、es或冗余字段优化。

LIKE 查询为什么慢?本质是索引失效
MySQL 的 LIKE 查询在模糊匹配时极易跳过索引,尤其是以通配符开头(如 LIKE '%abc')——这时优化器无法使用 B+ 树索引的有序性,只能全表扫描。即使字段上有索引,EXPLAIN 也会显示 type: ALL 或 key: NULL。
哪些 LIKE 形式能走索引?必须满足左前缀匹配
只有 LIKE 'abc%' 这类「固定前缀 + 后缀通配」才能利用索引的最左前缀原则。注意以下细节:
-
LIKE 'abc%'✅ 可用索引(B+ 树从 'abc' 开始向右遍历) -
LIKE 'ab%c'❌ 不可用(中间有通配符,无法确定范围边界) -
LIKE '%abc'❌ 不可用(无确定起始点) -
LIKE 'abc\_def'✅ 可用(_是单字符通配,不破坏前缀连续性) - 如果字段是
VARCHAR(255)但实际值平均长度仅 10,建索引时可考虑前缀索引:INDEX (col_name(10)),避免索引过大拖慢写入
无法改写为前缀匹配时,替代方案有哪些?
当业务必须支持任意位置匹配(如搜索标题含关键词),硬扛 LIKE '%keyword%' 性能极差,应换思路:
- 用全文索引:
ALTER TABLE t ADD FULLTEXT(col_name),再用MATCH(col_name) AGAINST('keyword' IN NATURAL LANGUAGE MODE)—— 支持分词、停用词、相关性排序,但只适用于MyISAM或InnoDB(5.6+) - 引入外部搜索引擎:Elasticsearch 或 Meilisearch,适合高并发、复杂检索场景;MySQL 仅存原始数据
- 冗余字段预处理:如提取关键词生成
tags字段,用FIND_IN_SET()或 JSON 匹配,配合普通索引 - 慎用
REGEXP:它比LIKE更慢,且完全无法用索引
字符集和排序规则对 LIKE 性能有隐性影响
同一查询在不同 collation 下可能走/不走索引。例如:
-
utf8mb4_unicode_ci:大小写不敏感,但比较开销大,且某些组合会让优化器放弃索引(尤其涉及函数隐式转换时) -
utf8mb4_bin或utf8mb4_0900_as_cs:二进制或大小写敏感排序,匹配更直接,索引利用率更高 - 检查字段 collation 是否与查询字面量一致:
SELECT COLLATION(col_name), COLLATION('abc');若不一致,MySQL 会隐式转换,导致索引失效 - 避免在
WHERE中对字段用函数:WHERE UPPER(col) LIKE '%ABC%'→ 索引必然失效
LIKE 上反复调参。










