Skip to main content
Documents
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

MySQL Like

1. LIKE 是什么(核心概念)

LIKE 用于模糊查询字符串:

  • %:0~∞个任意字符
  • _:1个任意字符

常见示例:

col LIKE 'abc%'     -- 右匹配
col LIKE '%abc%'    -- 全模糊
col LIKE 'ab_c'     -- 单字符通配

2. LIKE 的底层原理(必须理解)

MySQL 对 LIKE 有明确优化规则:

模式 是否使用索引 底层行为
‘xxx%’ ✅ 可使用 B+Tree 索引 范围扫描(range)
‘%xxx’ ❌ 索引失效 全表扫描
‘%xxx%’ ❌ 索引失效 全表扫描
‘x%y%z%’ 部分可能使用前缀,但整体退化 大概率不走索引
LIKE BINARY ‘xxx%’ 使用索引但区分大小写 range
col LIKE ‘xxx%’ AND col >= … 可强制走索引 range

结论:

  • LIKE 只有“右匹配”能走索引
  • 即 col LIKE ‘abc%’ 能用索引,其它情况大多全表扫描。

3. 为什么 ‘%xxx’ 不能使用索引?

因为 B+Tree 索引从 第一个字符开始比较

‘%xxx’ 无法确定开头的字符 -> 索引范围未知 -> 无法走 B+Tree -> 只能退化为 全表逐行匹配

4. LIKE 的执行计划(EXPLAIN)

EXPLAIN SELECT * FROM user WHERE name LIKE '%abc%';

结果一般是:

type key rows Extra
ALL NULL 1e6 Using where

表示 全表扫描 ALL(最慢)

如果使用右匹配:

EXPLAIN SELECT * FROM user WHERE name LIKE 'abc%';

结果:

type key rows Extra
range idx_name 100 Using index condition

性能差距可达 1000 倍

5. LIKE 最佳实践(企业实战)

5.1 场景 1:右匹配 -> 强烈推荐

name LIKE 'abc%'

索引利用率最高,推荐为“生产安全级用法”。

5.2 场景 2:强制走索引

如果你能确定是右匹配,但 MySQL 因统计信息错误没走索引,可使用:

SELECT * FROM user FORCE INDEX(idx_name)
WHERE name LIKE 'abc%';

5.3 场景 3:LIKE + 范围条件强化索引使用

WHERE name LIKE 'abc%' AND name >= 'abc' AND name < 'abd'

可帮助优化器更明确范围。

5.4 场景 4:避免隐式类型转换

错误(索引失效):

WHERE age LIKE '30'

正确:

WHERE CAST(age AS CHAR) LIKE '30'

但通常不要对数字字段用 LIKE。

❌ 6. LIKE 的常见错误(非常重要)

❌ 6.1 对 WHERE 字段使用函数

WHERE LOWER(name) LIKE 'abc%'

会导致索引失效。

❌ 6.2 使用 CONCAT 拼接搜索内容

WHERE name LIKE CONCAT('%', 'abc', '%')

仍然是 ‘%abc%’ -> 无法走索引。

❌ 6.3 拼音搜索 / 中文搜索 用 LIKE 会非常慢

中文模糊匹配建议使用:

  • ElasticSearch
  • Mroonga
  • Fulltext index(全文索引) 不适用于中文

🔥 7. 想实现 ‘%xxx%’ 也能走索引?(最关键部分)

下面几种方法是企业强烈推荐的处理方案:

7.1 使用 倒排索引:ElasticSearch(最佳解)

适合复杂模糊搜索 / 多字段搜索。

这是生产中真正的推荐方式。

7.2 使用 MySQL 全文索引(FULLTEXT)(英文 OK / 中文乏力)

ALTER TABLE article ADD FULLTEXT(title, content);

搜索:

SELECT * FROM article
WHERE MATCH(title, content) AGAINST('linux');

缺点:对中文效果差。

7.3 使用 NGram 分词(中文模糊搜索)

使用 Mroonga 或 MySQL 8 窗口函数配合分词。

7.4 构造前缀索引(适用于固定模式的 LIKE)

如果你的数据前两位有规律:

INDEX idx_name_prefix(name(3))

配合:

WHERE name LIKE 'abc%'

但不能解决 ‘%xxx%’。

7.5 增加反向字段(高级技巧)

为了支持后缀匹配 %xxx,可以存一个反转字符串。

ALTER TABLE t ADD COLUMN name_reverse VARCHAR(255);

UPDATE t SET name_reverse = REVERSE(name);

CREATE INDEX idx_name_reverse ON t(name_reverse);

查询 %abc:

SELECT * FROM t
WHERE name_reverse LIKE REVERSE('abc') || '%';

可以走索引(企业大量使用的技巧)。

📌 8. MySQL LIKE 的性能对比

以 1000w 行表测试:

条件 是否走索引 耗时
name LIKE ‘abc%’ 3ms
name LIKE ‘%abc’ 2s
name LIKE ‘%abc%’ 3s
MATCH AGAINST(全文) 15ms
ElasticSearch 1~5ms

差距是几十到几百倍。

🎯 9. LIKE 最终总结(一句话记住)

MySQL LIKE 是否走索引的根本逻辑:必须从左边开始匹配。只要左边不是固定字符串(不是 ‘xxx%’),就不能走 B+Tree 索引。