mysql全文索引需在create table或alter table时显式指定engine=innodb(≥5.6)或myisam,仅支持text/varchar字段,必须用match...against语法查询,中文需ngram分词器(8.0+)或应用层预分词。

创建表时直接加 FULLTEXT 索引
MySQL 的 FULLTEXT 索引只能在 CREATE TABLE 时或后续用 ALTER TABLE 添加,但必须明确指定引擎为 InnoDB 或 MyISAM(InnoDB 是当前推荐,默认且支持事务)。如果建表时不指定引擎,可能默认是 InnoDB,但 FULLTEXT 在旧版 MySQL(如 5.6 之前)的 InnoDB 中不被支持——务必确认版本 ≥ 5.6。
常见错误:建表语句里写了 FULLTEXT(title, content),但没写 ENGINE=InnoDB,结果报错 ERROR 1214 (HY000): The used table type doesn't support FULLTEXT indexes。
-
TEXT、VARCHAR字段才能建FULLTEXT,INT或BLOB不行 - 单列索引写法:
FULLTEXT (title);多列合并索引:FULLTEXT (title, content),两者查询语法不同 - 字段长度无硬性上限,但过短(如
VARCHAR(10))会导致很多词被忽略(默认最小词长为 4)
全文检索必须用 MATCH ... AGAINST 语法
建好 FULLTEXT 索引后,不能用 LIKE 或普通 WHERE 触发全文搜索。必须显式使用 MATCH(col1, col2) AGAINST('xxx' [IN NATURAL LANGUAGE MODE | IN BOOLEAN MODE]),否则索引完全不生效,变成全表扫描。
容易踩的坑:
- 字段顺序必须和
FULLTEXT定义一致:定义是FULLTEXT(title, content),那MATCH里也得写MATCH(title, content),调换顺序会报错ERROR 1191: Can't find FULLTEXT index matching the column list -
AGAINST的字符串必须是常量或参数,不能是字段名,比如AGAINST(other_column)会报错 - 自然语言模式(默认)对单字搜效果差;想搜“php”得开布尔模式:
AGAINST('+php' IN BOOLEAN MODE)
中文全文检索要额外处理分词
MySQL 原生 FULLTEXT 对中文支持极弱——它按空白和标点切词,而中文无空格。直接对中文字段建 FULLTEXT 索引,基本搜不到东西。
可行方案只有两个:
- 升级到 MySQL 8.0+ 并启用
ngram分词器:建表时加WITH PARSER ngram,例如FULLTEXT(title) WITH PARSER ngram,同时设置ngram_token_size=2(默认值,可调) - 应用层预分词:把标题/内容按词拆成带空格的字符串再存入,比如 “数据库优化” → “数据库 优化”,这样原生全文索引才能识别
- 不依赖 MySQL 全文:改用 Elasticsearch、MeiliSearch 或 SQLite 的 FTS5(如果场景允许换存储)
注意:ngram 只对 CHAR/VARCHAR/TEXT 生效,且只支持 InnoDB;MyISAM 不支持 ngram。
ALTER TABLE 添加 FULLTEXT 索引的注意事项
已有表想补全文索引,用 ALTER TABLE articles ADD FULLTEXT(title, content) 最直接。但这个操作会锁表(尤其数据量大时),在生产环境需谨慎。
- 如果表已有大量数据,建议在低峰期执行,并提前在测试库验证耗时
- 添加失败常见原因是字段类型不兼容:比如字段是
TEXT但用了utf8mb4_bin排序规则,某些旧版本会拒绝建索引;换成utf8mb4_general_ci或utf8mb4_0900_as_cs更稳妥 -
SHOW INDEX FROM articles可验证是否成功,Key_name列出现ft_title_content这类名字即表示存在
真正麻烦的不是怎么加,而是加完之后发现查不准、返回空、或者性能反而更差——这时候得回头检查分词逻辑、停用词列表(ft_stopword_file)、最小词长(ft_min_word_len)这些隐藏配置。











