MySQL 8.0全文索引对中文和短词无效是因默认配置限制:innodb_ft_min_token_size=3丢弃“AI”等短词,未启用ngram解析器导致中文切分失败,且停用词表过滤影响匹配;必须关闭停用词、调小token长度、重启服务并重建带ngram解析器的索引,同时将高频WHERE条件列前置索引才能生效。

MySQL 8.0 的全文索引不是“加了就快”的银弹,它只对 MATCH() AGAINST() 有效,且默认对中文、短词(如“AI”“DB”)完全不索引——直接建索引后搜不到结果,是配置和用法没对,不是索引本身有问题。
为什么 MATCH('关键词') 返回空或慢得离谱?
常见现象:建了 FULLTEXT(title, content),但 MATCH(title, content) AGAINST('AI优化') 查不到任何行,或 EXPLAIN 显示 rows 接近全表量级。
- 默认
innodb_ft_min_token_size = 3,所以 “AI”(2 字符)、“云”(1 字符)被直接丢弃,查不到 - 中文未启用
ngram解析器,MySQL 把整段中文当一个超长 token 切分失败,词典里几乎没词 -
IN NATURAL LANGUAGE MODE下,AGAINST()内部会做相关性重排,无法下推条件,哪怕你加了WHERE status = 'published',也得等全文扫描完再过滤 - 停用词表默认开启(
innodb_ft_enable_stopword = ON),搜“数据库的优化”时,“的”被过滤,实际只搜“数据库 优化”,匹配逻辑断裂
必须改的三项全局配置与重建索引
这些不是“建议”,是中文/短词场景下生效的前提。改完不重启 + 不重建索引 = 白改。
- 关停用词:
SET GLOBAL innodb_ft_enable_stopword = OFF; - 调小最小词长:
SET GLOBAL innodb_ft_min_token_size = 2;(若需索引单字,设为 1;但会显著增大索引体积) - 重启 MySQL 实例(
systemctl restart mysqld或 Windows 服务),否则配置不加载进 InnoDB 引擎层 - 重建全文索引:
ALTER TABLE articles DROP INDEX ft_idx; ALTER TABLE articles ADD FULLTEXT ft_idx (title, content) WITH PARSER ngram;——WITH PARSER ngram必须显式写,否则中文仍不生效
查询写法决定是否真走索引过滤
全文索引能否和业务条件协同过滤,取决于索引结构和 WHERE 子句写法,不是靠优化器自动识别。
- 要把高频等值条件列(如
status、category_id)放进全文索引最左侧:ADD FULLTEXT(status, title, content),这样WHERE status = 'published' AND MATCH(title, content) AGAINST(...)才能先用status定位数据段,再在子集里查全文 -
MATCH()必须出现在WHERE最外层,不能嵌套:WHERE id IN (SELECT ...)或WHERE MATCH() AGAINST() AND created_at > '2025-01-01'中,后者created_at条件无法参与索引下推 - 布尔模式(
IN BOOLEAN MODE)支持+/-/*,但必须带引号写完整词:AGAINST('+MySQL -Oracle' IN BOOLEAN MODE);写成AGAINST('+My*' IN BOOLEAN MODE)才能前缀通配,'My*'不加引号会报语法错
别碰 INSTR / LIKE / 正则,它们和全文索引互斥
有人想“绕过语法限制”,用 INSTR(content, 'AI') > 0 或 content REGEXP 'AI|优化' —— 这些函数永远触发全表扫描,EXPLAIN type 一定是 ALL,且无法利用任何全文索引。
-
LIKE '%AI%'和INSTR(content, 'AI')在执行计划上完全等价,都是逐行计算,索引形同虚设 - 全文索引只响应
MATCH() AGAINST(),其他写法哪怕字段上有FULLTEXT索引也完全不走 - 如果业务必须支持任意位置模糊(如用户输入框实时搜索),又不愿引入 Elasticsearch,唯一可行路径是预处理:用 Python 脚本把原文分词后写入关联关键词表,再建普通索引,而非硬扛全文索引的语法规则
真正卡住性能的,往往不是索引建没建,而是 ngram 没指定、innodb_ft_min_token_size 没调、索引列顺序没按业务 WHERE 条件排列——这三个点漏掉任一个,全文索引就退化成摆设。











