MySQL默认FULLTEXT索引不支持中文,需启用ngram分词并设ngram_token_size=2、ft_min_word_len=2,建索引时必须显式指定WITH PARSER ngram且表引擎为InnoDB,修改后须重启MySQL并重建全文索引。

MySQL 默认的 FULLTEXT 索引对中文基本无效,不是配置没调好,而是设计上就不支持无空格语言——直接建索引、用 MATCH() AGAINST() 查“编程”,根本不会命中“我爱编程”这种字段。必须引入分词机制,否则所有优化都是徒劳。
ngram_token_size 设得太大会漏词
ngram 是 MySQL 5.7+ 内置的中文分词方案,靠滑动窗口切字,但粒度选错就等于没分。比如设成 ngram_token_size=4,“人工智能”只会拆出“人工智能”一个 token,查“智能”就找不到;设成 1 虽然能拆单字,但噪音爆炸(“的”“了”“在”全进索引),查询精度反而下降。
- 生产环境推荐从
ngram_token_size=2起步,兼顾覆盖率和噪声控制 - 修改后必须重启 MySQL,
SHOW VARIABLES LIKE 'ngram_token_size'确认生效,不能只改配置文件就以为完事 - 已有数据的表,改完配置后需重建全文索引:
ALTER TABLE articles DROP INDEX ft_idx; ALTER TABLE articles ADD FULLTEXT INDEX ft_idx (title, content) WITH PARSER ngram;
CREATE FULLTEXT 时漏写 WITH PARSER ngram
即使 ngram_token_size 配好了,建索引时没显式指定解析器,MySQL 仍用默认分词逻辑(按空格/标点切),中文字段实际没被分词。错误写法:ALTER TABLE articles ADD FULLTEXT INDEX ft_idx (content); —— 这条命令完全无视 ngram 配置。
- 必须带
WITH PARSER ngram,且只能用于 InnoDB 表(MyISAM 不支持该语法) - 多列联合索引时,所有列必须同字符集和排序规则,否则建索引失败,报错
ERROR 1287 - 确认表引擎:
SHOW CREATE TABLE articles;中看到ENGINE=InnoDB才安全
ft_min_word_len 设为默认值 4 导致短词丢失
中文里大量有效词是 2 字或 3 字,比如“AI”“云原生”“Redis”。但 MySQL 默认 ft_min_word_len=4,这些词直接被过滤掉,索引里压根没有。
- 编辑
my.cnf,在[mysqld]下加ft_min_word_len=2(不建议设为 1,单字检索噪音太大) - 改完必须重建全文索引,
REPAIR TABLE articles QUICK;或OPTIMIZE TABLE articles;都不行,只有删索引再建才生效 - 注意:该参数影响所有全文索引,不是单表设置,改前需评估对其他表的影响
最常被忽略的一点:ngram 分词本质是“按字切片”,不是语义分词。“人工智能”切成“人工 / 工智 / 智能”,查“人工”能命中,“智能”也能,但查“AI”或“AI智能”就毫无意义——它解决不了歧义和同义问题。真要语义级搜索,得上 Elasticsearch 或应用层预分词(如用 jieba 处理后再入库),MySQL 全文索引只是个带分词能力的快速筛选器,不是搜索引擎。


















