mysql like模糊查询如何优化_mysql模糊匹配性能技巧

来源:这里教程网 时间:2026-02-28 20:47:41 作者:

LIKE 以通配符开头时索引完全失效

MySQL 的

LIKE
查询中,只要左侧是通配符(如
'%abc'
'%abc%'
),即使字段上有 B+ 树索引,优化器也会放弃使用索引,转为全表扫描。这是性能骤降的最常见原因。

实操建议:

能用
=
IN
就不用
LIKE
—— 比如状态码、类型标识等固定值匹配
若必须前缀模糊(如搜索“包含某词”),优先考虑
LIKE 'abc%'
,它可走索引(最左前缀匹配)
避免在索引字段上做函数操作,例如
LOWER(name) LIKE '%xxx%'
会彻底禁用索引

全文索引(FULLTEXT)更适合中文分词场景

对长文本字段(如文章标题、商品描述)做模糊匹配时,

FULLTEXT
索引比
LIKE
更高效,尤其配合
MATCH ... AGAINST
使用。但注意:MyISAM 和 InnoDB 都支持,但 InnoDB 要求 MySQL ≥ 5.6,且中文需依赖内建分词器或第三方插件(如 ngram)。

实操建议:

建表时添加
FULLTEXT(title, content)
,不要等查询慢了再加
查询写法必须是
MATCH(title) AGAINST('关键词' IN NATURAL LANGUAGE MODE)
,不能混用
LIKE
ngram 分词长度默认为 2,若搜单字(如“李”),需设
ft_min_word_len=1
并重建索引(有风险,慎调)

前导通配符场景下,用生成列 + 函数索引兜底(MySQL 5.7+)

当业务强依赖

LIKE '%xxx'
(后缀匹配),又无法改查询逻辑时,可借助生成列(generated column)把反转字符串存下来,再对其建索引。

示例:

ALTER TABLE users 
ADD COLUMN name_reversed VARCHAR(100) AS (REVERSE(name)) STORED,
ADD INDEX idx_name_rev (name_reversed);

然后将原查询

WHERE name LIKE '%john'
改为:

WHERE name_reversed LIKE CONCAT(REVERSE('john'), '%')

这样就能命中

idx_name_rev
索引。注意:
STORED
生成列会占用磁盘空间,且写入略慢;
VIRTUAL
不落盘但无法建索引。

LIKE 查询被误判为范围扫描导致执行计划失真

有时

EXPLAIN
显示
type=range
,看似走了索引,但实际扫描行数极大(
rows
值高),这是因为优化器按“最左前缀”估算,而
LIKE 'abc%'
后续字符分布不均(比如大量以
'abc1'
开头),导致索引选择性差。

排查与应对:

SHOW INDEX FROM table
查看
Cardinality
,越接近总行数说明区分度越高
对低区分度字段(如性别、状态),别单独建索引,考虑联合索引中放后面 必要时加
FORCE INDEX
强制走某个索引,但要配合
EXPLAIN
验证效果
真正卡住性能的,往往不是模糊语法本身,而是没意识到索引是否生效、或者误信“加了索引就万事大吉”。尤其在
LIKE
中混用函数、隐式类型转换、或跨多字段拼接条件时,执行计划很容易偏离预期。

相关推荐