国内海外服务器测评及优惠
Linux服务器运维救灾服务

LIKE ‘c%’ 导致索引失效的替代方案(全文索引 / ngram)

LIKE ‘%abc%’ 无法使用B+树索引,因其前导通配符破坏有序性,导致优化器无法确定扫描起点,只能全表扫描;应改用FULLTEXT索引配合MATCH…AGAINST查询。

LIKE '%abc%' 一定走不了 B+ 树索引

因为 B+ 树索引依赖有序性,而前导通配符(% 开头)让优化器无法确定扫描起点。即使字段有索引,MySQL 也只能全表扫描——这不是配置问题,是 B+ 树结构本身的限制。

常见误操作:ALTER TABLE t ADD INDEX idx_name (name) 后仍慢,就说明没绕过这个根本约束。

FULLTEXT 索引 + MATCH ... AGAINST 替代(适合长文本)

全文索引不依赖前缀匹配,而是对词元(token)建立倒排索引,天然支持中间匹配。但要注意:它默认只对长度 ≥ 4 的词建索引(ft_min_word_len=4),且对停用词、标点敏感。

  • 建索引:ALTER TABLE t ADD FULLTEXT(name)
  • 查询写法必须用:SELECT * FROM t WHERE MATCH(name) AGAINST('abc' IN NATURAL LANGUAGE MODE)(不能用 LIKE 语法)
  • 若要精确匹配子串(如 ‘abc’ 作为独立词出现),改用布尔模式:AGAINST('+abc' IN BOOLEAN MODE)
  • 中文需额外配置:innodb_ft_parser=ngram + ngram_token_size=2(见下节)

MySQL 5.7+ 的 ngram 分词器怎么配才生效

ngram 是 MySQL 内置的中文分词方案,把字符串按固定长度切片(如 ngram_token_size=2 时,’abc’ → [‘ab’, ‘bc’]),再对切片建倒排索引。但它只作用于 FULLTEXT 索引,且必须显式启用。

一站式AI应用开发和部署工具

  • 建表时指定解析器:CREATE TABLE t (name TEXT, FULLTEXT(name) WITH PARSER ngram)
  • 或建索引时指定:ALTER TABLE t ADD FULLTEXT(name) WITH PARSER ngram
  • ngram_token_size 影响粒度:值越小,切得越细,查短词越准,但索引体积越大;查 ‘abc’ 至少要设为 2 或 3
  • 查询仍用 MATCH ... AGAINST,但支持更自然的中文子串意图,比如搜 ‘数据库’ 可能命中 ‘关系型数据库’ 中的 ‘数据库’ 片段

真正需要 LIKE '%abc%' 语义时,别硬扛索引

如果业务强依赖任意位置的模糊匹配(比如日志关键词检索、用户输入即搜),又不想引入 Elasticsearch,可以接受一定延迟和资源开销,那直接上 WHERE name LIKE '%abc%' 并加 FORCE INDEX 没意义——不如提前剪枝:

  • 加长度过滤:WHERE LENGTH(name) >= 3 AND name LIKE '%abc%',减少扫描行数
  • 用生成列 + 普通索引加速常见模式:ALTER TABLE t ADD COLUMN name_abc TINYINT GENERATED ALWAYS AS (CASE WHEN name LIKE '%abc%' THEN 1 ELSE 0 END) STORED,再对 name_abc 建索引(适合固定关键词)
  • 高频子串可预计算哈希(如 MURMUR3)存到额外列,用等值查询替代模糊匹配

ngram 和 FULLTEXT 都不是万能的,它们改变的是“匹配单位”(从字符串到词元/切片),而不是绕过 MySQL 的查询执行模型。上线前务必用 EXPLAINtype 是否变成 fulltext,以及 key 是否显示你建的全文索引名。

赞(0) 打赏
未经允许不得转载:linuxcto运维 » LIKE ‘c%’ 导致索引失效的替代方案(全文索引 / ngram)

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫