MySQL全文索引失效取决于存储引擎、字符集、最小词长、停用词表、查询语法五大门槛:MyISAM原生支持且宽松,InnoDB从5.6起支持但限制严格;仅VARCHAR/TEXT列且utf8mb4等字符集可用;最小词长默认3,停用词如“the”被过滤;MATCH字段顺序、名称须与索引定义完全一致;布尔模式需显式声明IN BOOLEAN MODE;词尾通配search*有效,但不支持左模糊或中模糊。

MySQL全文索引失效,不是“加了就一定能用”,而是取决于存储引擎、字符集、最小词长、停用词表、查询语法这五个硬性门槛——跨过一个都可能白搭。
MyISAM全文索引能用但InnoDB不生效?先看存储引擎限制
MyISAM原生支持FULLTEXT索引,且对停用词、最小词长更宽松;InnoDB从5.6才开始支持全文索引,但默认行为更严格,很多老项目迁移后直接“静默失效”。
- 确认表引擎:
SHOW CREATE TABLE table_name,检查是否为ENGINE=InnoDB - InnoDB全文索引仅支持
VARCHAR、TEXT列,且必须是utf8mb4或latin1等支持分词的字符集(utf8别名在MySQL 8.0+已弃用,实际指utf8mb3,不支持某些emoji分词) - MyISAM允许在
CHAR列建全文索引,InnoDB不允许——若建表语句里写了FULLTEXT(col)但col是CHAR(20),InnoDB会忽略该索引,SHOW INDEX里根本看不到
EXPLAIN显示type=ALL、key=NULL?重点查分词配置
InnoDB全文索引不是“模糊匹配”,而是基于倒排索引的词项检索,如果查询词被过滤掉,就等于没查任何东西。
- 检查最小词长:
SELECT @@innodb_ft_min_token_size;(默认3),若搜'go'或'a',直接被丢弃,查不到结果也不报错 - 查看停用词表:
SELECT @@innodb_ft_server_stopword_table;,默认启用内置停用词表,'the'、'and'、'is'等常见词全被跳过 - 临时绕过停用词:建表时指定空停用词表:
SET GLOBAL innodb_ft_server_stopword_table='';(需SUPER权限),或建表时显式设WITH PARSER ngram并配ngram_token_size
MATCH() AGAINST()返回空?语法和字段必须完全对齐
全文查询不是WHERE条件拼接,MATCH里的字段顺序、数量、类型必须和FULLTEXT索引定义一模一样。
- 索引建在
(title, content),但写MATCH(title) AGAINST(...)→ 失效(字段数不匹配) - 索引建在
content,但查询写MATCH(`content `) AGAINST(...)(带空格)→ 失效(字段名不一致) - 使用布尔模式却漏写
IN BOOLEAN MODE:默认是自然语言模式,对短词、停用词更敏感,且不支持+、-等操作符 - 自然语言模式下
AGAINST('mysql tutorial')会被拆成两个独立词搜索并加权,不是短语匹配;要精确匹配短语,必须用布尔模式:AGAINST('+mysql +tutorial' IN BOOLEAN MODE)
为什么ANALYZE TABLE后还是不走全文索引?
InnoDB全文索引依赖内部的辅助表(如FTS_0000000000000123_0000000000000123_INDEX_1),这些表不会随ANALYZE TABLE更新。真正有效的是重建索引本身。
- 强制刷新全文索引缓存:
SET GLOBAL innodb_optimize_fulltext_only=ON;,再执行OPTIMIZE TABLE table_name; - 更彻底的办法:删掉全文索引再重建:
ALTER TABLE table_name DROP INDEX ft_idx_name;→ALTER TABLE table_name ADD FULLTEXT INDEX ft_idx_name (col1, col2); - 注意:重建期间表会被锁(InnoDB行锁,但全文索引重建涉及辅助表,实际是DML阻塞),线上大表慎用
全文索引失效最常被忽略的一点:它根本不是为“左模糊”或“任意位置匹配”设计的。哪怕你用了IN BOOLEAN MODE,*wildcard也只支持词尾通配(search*),不支持*arch或*earc*。真要实现这类需求,别硬扛全文索引——上LIKE '%...%'配覆盖索引,或切到Elasticsearch。











