mysqllike查询如何走索引_mysql模糊查询优化

1次阅读

能,但仅限 like ‘abc%’ 这类前缀匹配;like ‘%abc’ 或 like ‘%abc%’ 默认无法使用 b+ 树索引,因 b+ 树只支持从左到右匹配,开头通配符导致无法定位起始位置而全表扫描。

mysqllike查询如何走索引_mysql模糊查询优化

LIKE 查询能走索引吗?取决于通配符位置

能,但仅限 LIKE 'abc%' 这类前缀匹配;LIKE '%abc'LIKE '%abc%' 默认无法使用 B+ 树索引(除非用覆盖索引或倒排索引方案)。

mysql 的 B+ 树索引是按字典序存储的,只能高效支持「从左到右」的匹配。一旦开头是通配符,优化器就无法定位起始位置,只能全表扫描。

  • LIKE '张%' → 可走 name 索引(前提是该列有索引)
  • LIKE '%三' → 不走索引,哪怕 name 有索引
  • LIKE '%王%' → 同样不走索引,且无法利用前缀树特性

为什么加了索引还是没走?检查这几个点

即使写成 LIKE 'abc%',也可能因隐式类型转换、函数包裹或统计信息过期导致索引失效。

  • 字段类型和参数类型不一致:比如 name VARCHAR(50) 被和整数比较,触发隐式转换 → WHERE name LIKE 123 会全表扫
  • 在字段上用了函数:WHERE UPPER(name) LIKE 'ABC%' → 索引失效(可建函数索引:CREATE INDEX idx_name_upper ON t1 ((UPPER(name)))
  • 查询条件中混用 OR 且部分分支无索引:WHERE name LIKE 'a%' OR status = 1,可能让整个查询放弃索引
  • 优化器认为全表扫描更快:比如表小、匹配行数多(> ~20% 总行数),可通过 EXPLAINtype 是否为 rangeref

后缀/中缀模糊查怎么优化?绕不开的几个替代方案

真要查 '%关键词''%关键词%',原生 B+ 索引无解,得换思路:

  • 全文索引(FULLTEXT):适合中文需配合 ngram 插件(MySQL 5.7+),建索引:ALTER table t1 ADD FULLTEXT(name),查:select * FROM t1 WHERE MATCH(name) AGAINST('三' IN NATURAL LANGUAGE MODE)
  • 倒排表 / 冗余字段:把字符串拆成关键词存进关联表,或生成反向字符串字段(如 name_reverse),对后缀查转为前缀查:WHERE name_reverse LIKE REVERSE('三') + '%'
  • 前缀索引 + 应用层过滤:对长文本建前缀索引(INDEX idx_name_10 (name(10))),先快速筛出可能项,再由应用做二次匹配
  • ES 或 RedisSearch:超出 MySQL 能力边界时,应考虑专用搜索服务

LIKE 查询性能差的典型信号

别等用户投诉才查,这些现象说明模糊查询已成瓶颈:

  • EXPLAIN 结果中 rows 值极大,且 typeALL
  • SHOW PROFILE for QUERY N 显示 Copying to tmp tableCreating sort index 耗时占比高
  • 慢日志里反复出现 LIKE '%...'Query_time > 1s
  • 并发稍高时 CPU 持续 90%+,SHOW PROCESSLIST 多个状态为 Sending data

模糊查询的“模糊”本身就在牺牲确定性,越想查得全,越难快——真正需要的是明确业务场景下「够用」的精度和速度平衡,而不是强行让 LIKE '%xxx%' 走索引。

text=ZqhQzanResources