LIKE '%value%' 查询慢是因为无法使用B+树索引,只能全表扫描;全文索引可替代但有类型、分词和中文支持等限制;复杂场景应选Elasticsearch。

LIKE '%value%' 为什么慢得像卡住
因为没法用普通索引。B+ 树索引只对最左前缀有效,LIKE '%value%' 是从中间或末尾匹配,MySQL 只能全表扫描。哪怕加了 name 上的索引,只要开头是 %,就自动失效。
常见错误现象:EXPLAIN 显示 type: ALL、rows 接近表总行数、查询耗时随数据量陡增;线上慢查日志里反复出现这类语句。
这不是写法“不够优雅”的问题,是底层索引机制决定的硬限制。
全文索引(FULLTEXT)能直接替换 LIKE 吗
能,但有严格前提:只适用于 MyISAM 或 InnoDB 表,且字段类型必须是 CHAR、VARCHAR 或 TEXT;不支持单字符、停用词(如“的”“和”)、小于 4 字符的词(默认 ft_min_word_len=4,可调但需重启)。
实操建议:
- 建索引:
ALTER TABLE articles ADD FULLTEXT(title, content); - 查法不是
LIKE,得用MATCH ... AGAINST:SELECT * FROM articles WHERE MATCH(title) AGAINST('数据库' IN NATURAL LANGUAGE MODE); - 注意模式差异:
NATURAL LANGUAGE MODE不支持通配符;要模糊匹配得切到BOOLEAN MODE,比如AGAINST('+data*' IN BOOLEAN MODE)(*必须在词尾) - 中文需要额外处理:MySQL 原生 FULLTEXT 对中文分词支持极弱,基本只能靠第三方插件(如
ngram分词器),启用前务必验证分词效果
什么时候该跳过 MySQL 全文索引,直接上 Elasticsearch
当你的场景出现以下任意一条,FULLTEXT 就力不从心了:
- 要高亮搜索结果(
HIGHLIGHT) - 需要拼写纠错(
fuzzy查询)、同义词扩展、拼音搜索 - 数据实时性要求高(FULLTEXT 的
INNODB同步延迟不可控,ES 可设refresh_interval到 1s) - 字段多、过滤条件复杂(比如 “标题含‘MySQL’且状态=1且创建时间>7天前”),ES 的布尔查询更清晰
代价也很实在:多一套服务运维、数据双写一致性要自己兜底、学习曲线比 MATCH AGAINST 高不少。小项目别一上来就堆 ES。
如果暂时不能换方案,怎么临时压住 LIKE 的性能火苗
不是所有 LIKE '%value%' 都必须干掉,有些可以“骗过”优化器或缩小扫描范围:
- 加前置过滤条件,把
WHERE status = 1 AND content LIKE '%error%'改成WHERE status = 1 AND content LIKE '%error%' AND id > 100000,利用主键范围减少扫描行数 - 拆字段:把长文本里的关键标签提前抽成独立字段(如
tag_list VARCHAR(255)),用FIND_IN_SET('redis', tag_list)或JSON_CONTAINS替代全文扫 - 用生成列 + 普通索引:MySQL 5.7+ 支持生成列,比如
content_digest VARCHAR(32) AS (MD5(content)) STORED,虽然不能搜内容,但能快速排除大量不匹配记录 - 缓存层兜底:高频固定关键词(如后台搜“支付失败”)直接走 Redis Hash 存 ID 列表,避免碰 DB
这些只是止痛药,不是根治。真正要支撑海量文本模糊检索,绕不开分词、倒排、分布式这几个坎儿——而 MySQL 没打算替你扛。










