能走索引的只有like 'abc%'类前缀匹配;'%abc'和'%abc%'必然全表扫描;需满足字段有索引、未被函数包裹、位于联合索引最左位置,且排序规则与查询大小写一致。

能走索引的只有 LIKE 'abc%' 这类前缀匹配;LIKE '%abc' 和 LIKE '%abc%' 基本等于全表扫描,别指望它快。
LIKE 什么时候能用上索引?
MySQL 的 B+ 树索引只支持“从左到右”的有序查找,所以只有模式开头是确定字符串、结尾是 % 时,才能定位起始位置并范围扫描。
-
LIKE '张%'→ 可走索引(前提是name列有 B+ 树索引) -
LIKE '张_丰'→ 仍可走索引(_占一位,前缀连续) -
LIKE '张%丰'→ 索引失效(中间断开,无法跳过未知长度段继续比对) -
LIKE '%丰'→ 全表扫描(没起点,只能从头扫)
别光建 INDEX(name) 就以为万事大吉。如果查询还带 OR、字段被函数包裹(比如 UPPER(name) LIKE 'A%')、或参数类型不匹配(比如 WHERE name LIKE 123),优化器照样会放弃索引。
如何安全地匹配含 % 或 _ 的字面量?
当你要查的字符串里真包含 % 或 _(比如用户名是 admin%),直接写 LIKE '%admin%%' 会被当成通配符处理——结果不是你想要的。
- 用
ESCAPE指定转义字符,例如:WHERE name LIKE '%admin\%%' ESCAPE '\' - 也可以换别的转义符,比如:
WHERE name LIKE '%admin!%' ESCAPE '!' - 注意:转义符本身必须在 pattern 中出现两次才表示字面量,如
'%!%' ESCAPE '!'匹配的是%字符
漏写 ESCAPE 或转义符写错位置,会导致查不到数据或误匹配——这种问题在线上很难复现,但一出就是漏查。
BINARY 能解决大小写敏感问题吗?
默认情况下,LIKE 是否区分大小写,取决于字段的排序规则(collation)。比如 utf8mb4_0900_ai_ci 是不区分的,而 utf8mb4_0900_as_cs 是区分的。
- 临时强制区分大小写:
WHERE name LIKE BINARY 'Alice' - 但
BINARY会让索引失效(相当于对字段加了隐式函数),前缀匹配也走不了索引 - 更稳妥的做法是建表时就选带
cs(case-sensitive)后缀的 collation,比如utf8mb4_0900_as_cs
别在 WHERE 里随手加 BINARY 就以为解决了问题——它只是把问题从“查不准”换成了“查得慢”。
NULL 值为什么永远不匹配 LIKE?
NULL 不参与任何比较运算,NULL LIKE '%a%' 结果是 NULL(不是 TRUE 或 FALSE),所以整行被过滤掉。
- 想同时查非空且模糊匹配的记录,得显式排除:
WHERE name IS NOT NULL AND name LIKE '%a%' - 如果业务允许
NULL也算一种有效值,就得拆成两个条件:WHERE name LIKE '%a%' OR name IS NULL
这个细节常被忽略,尤其在拼接动态 SQL 或 MyBatis 的 <if></if> 标签里——一个 IS NULL 没补上,线上就丢数据。











