全文索引适合语义级模糊匹配场景,如多词组合搜索文章、商品描述或客服工单;要求字段长度>10字符、内容松散、不依赖精确前缀或大小写,且需配合中文分词插件(如ngram)方可有效支持中文。

全文索引适合什么场景
MySQL 的 FULLTEXT 索引不是万能的,它只在特定文本检索场景下才有意义。真正适合用它的,是那些需要「语义级模糊匹配」的查询,比如用户搜索文章标题或正文关键词、商品描述中找“防水 蓝牙 降噪”这类多词组合、客服工单里查“无法登录 密码错误”。
FULLTEXT 对中文支持有限(5.7+ 需配合 ngram 插件,8.0+ 支持 zhparser 或自定义分词器),所以实际用在中文场景前得先确认分词是否生效;而英文、数字混合命名的字段(如日志消息、错误堆栈)反而更稳妥。
- 查询条件里包含至少两个有意义的词(单个词如“的”“和”会被停用词过滤掉)
- 字段长度通常 > 10 个字符,且内容结构松散(非固定格式 ID/编码)
- 不要求精确前缀匹配,也不依赖大小写或标点
Like '%keyword%' 为什么慢
LIKE 带前后通配符('%abc%')时,MySQL 无法使用普通 B+ 树索引做有效跳转,只能全表扫描 + 逐行字符串匹配。哪怕字段上有索引,只要左边有 %,索引就形同虚设。
常见误用:
-
WHERE content LIKE '%mysql%优化%'—— 多词模糊,无索引加速 -
WHERE title LIKE CONCAT('%', ? ,'%')—— 参数化也救不了,执行计划里type是ALL - 在大表(百万行以上)上跑这种查询,响应常超数秒,且并发一高就堵住 I/O
注意:只有 LIKE 'prefix%' 这种左匹配才可能走索引,但本质是范围扫描,仍不如 FULLTEXT 对多词布尔逻辑的支持。
Match Against 性能比 Like 好在哪
MATCH ... AGAINST 走的是倒排索引,把词拆出来建映射表,查“数据库 优化”时,引擎直接定位到同时含这两个词的文档 ID 列表,再按相关度排序。
实测对比(InnoDB,120 万行 blog 表,content TEXT 字段):
-
LIKE '%数据库%优化%':平均 3.2s,执行计划显示rows: 1245678 -
MATCH(content) AGAINST('数据库 优化' IN NATURAL LANGUAGE MODE):平均 0.08s,rows: 42(仅扫描匹配行)
但要注意几个硬约束:
- 表必须是
MyISAM或InnoDB(5.6+),且字段类型为CHAR/VARCHAR/TEXT - 查询词不能少于
ft_min_word_len默认值(通常 4),否则搜“sql”会失败 -
AGAINST中的字符串不能是变量或拼接结果,必须是字面量或用户变量(但变量需提前 SET,且不支持 PREPARE 绑定)
容易被忽略的坑
FULLTEXT 看似开箱即用,但线上出问题往往卡在细节:
- 中文字段没启用
ngram,SHOW VARIABLES LIKE 'ngram_token_size'返回空,意味着所有中文查询都返回空结果 - 没重建索引:加了
FULLTEXT后新增的数据能查,但历史数据不会自动进倒排索引,需ALTER TABLE t ADD FULLTEXT(content);后触发一次OPTIMIZE TABLE t; - 相关度阈值太敏感:
NATURAL LANGUAGE MODE下,匹配度低于 0.2 的行默认不返回,调试时加SELECT MATCH(...) AGAINST(...) AS score看具体值 - 停用词表被改过:自定义停用词文件未加载,或
ft_stopword_file指向错误路径,导致“mysql”“server”之类高频词被静默过滤
全文索引不是替代 LIKE 的通用方案,它是为“人找信息”设计的,不是为“程序校验字符串”准备的。字段里存的是 UUID、手机号、订单号?别费劲建 FULLTEXT,老实用 = 或前缀索引。











