模糊字符串匹配不能只靠LIKE '%xxx%',需按场景选择前缀、后缀、固定长度等写法;无通配符时等价于等值查询,'%'前置必然全表扫描,'\_'是严格单字符占位符,字符集与转义规则直接影响结果。

直接说结论:模糊字符串匹配不能只靠 LIKE '%xxx%' 硬套,否则在百万级表上查一次可能卡住整个应用。真正可用的方案得看场景——是前缀查、后缀查、固定长度匹配,还是带字符集约束?每种写法对索引、性能、语义的影响都不同。
LIKE 后没通配符时,其实走的是等值查询
很多人写 WHERE name LIKE '张三' 却以为自己在“模糊查”,其实 MySQL 优化器会把它当 = '张三' 处理。这不是 bug,是设计行为。但问题在于:一旦你后续改成 LIKE '张三%',哪怕只加一个 %,索引使用逻辑就彻底变了。
- 无通配符 → 可走 B-Tree 索引(如果列有索引)
-
LIKE '张%'→ 可走索引前缀扫描(高效) -
LIKE '%张%'→ 几乎必然全表扫描(除非启用了全文索引或倒排索引) -
LIKE '_张%'→ 仍无法用索引加速,因为首字符不确定
下划线 _ 不是“可选字符”,而是强制占位符
_ 的语义非常严格:它必须匹配且仅匹配一个字符,不能多也不能少,也不能跳过。比如 LIKE 'A_B_C' 要求字符串总长恰好为 5,第1位是 A,第3位是 B,第5位是 C,中间两个位置必须各有一个字符(任意值)。
- 想查“所有三字姓名”?用
LIKE '___',不是LIKE '%%%' - 想查“以‘王’开头、第二字不是‘小’的四字名”?写
LIKE '王[^小]__'(注意:MySQL 8.0+ 才支持[^...]语法) - 在低版本 MySQL 或 SQLite 中,
[...]和[^...]不被识别,会当作普通字符串字面量处理,导致查不到数据
前导 % 是性能杀手,但有时能绕开
真正让 DBA 头疼的是 LIKE '%关键词' 这类后缀匹配,因为它无法利用常规 B-Tree 索引。常见误区是“加个联合索引就能解决”,但实际无效——索引按字典序组织,而 %关键词 要求从末尾反向匹配。
- 可行替代方案:建生成列 + 函数索引,例如 MySQL 8.0+ 支持
ALTER TABLE t ADD COLUMN name_reversed VARCHAR(100) AS (REVERSE(name)) STORED,再对name_reversed建索引,查询改写为WHERE name_reversed LIKE REVERSE('关键词') + '%' - 更轻量做法:业务层控制——比如只允许用户输前缀,禁止纯中间匹配;或把高频后缀词单独落库做映射表
- 千万别在 WHERE 里对字段套函数,如
WHERE SUBSTR(name, -3) = '老师',这会让索引完全失效
字符集和排序规则影响匹配结果
同一个 LIKE '李%' 在 utf8mb4_general_ci 和 utf8mb4_0900_as_cs 下行为可能完全不同。前者不区分大小写、忽略重音,后者区分大小写且严格按 Unicode 码点比较。
- 执行
SHOW CREATE TABLE t查看列的COLLATE设置 - 临时覆盖排序规则可用
COLLATE utf8mb4_bin,例如WHERE name COLLATE utf8mb4_bin LIKE 'Li%' - 如果字段是
utf8mb4_unicode_ci,那么LIKE 'cafe%'可能意外匹配到café(带重音符号),因为该 collation 把它们视为等价
最常被忽略的一点:通配符本身也是字符串的一部分,如果要查真实存在的 % 或 _ 字符,必须用 ESCAPE 显式转义,比如 LIKE '100\%' ESCAPE '\',否则数据库会当成通配含义解析——这个细节在线上出过不少生产事故。

















