MySQL 5.7+ 中文全文索引默认不生效,因其原生InnoDB全文索引依赖空格/标点分词,而中文无自然分隔符,导致整段文本被当做一个token,无法匹配子词;必须显式指定WITH PARSER ngram并配置ngram_token_size与innodb_ft_min_token_size一致才可正常切分中文。

MySQL 5.7+ 中文全文索引为什么默认不生效
因为 MySQL 原生的 INNODB 全文索引对中文支持极弱:它按空格和标点分词,而中文词与词之间没有空格,导致整条留言被当作一个“词”,无法匹配子串或关键词。你执行 MATCH(content) AGAINST('登录') 很可能返回空结果,不是 SQL 写错了,是分词根本没切开。
解决路径只有两条:改用 ngram 分词器(推荐),或把中文预处理成带空格的格式(不实用)。MySQL 5.7 起才正式支持 ngram,且仅作用于 CHAR、VARCHAR、TEXT 类型字段。
- 建表时必须显式指定
ft_parser=ngram,仅加FULLTEXT索引不够 -
ngram_token_size默认为 2,即按 2 字切分(“用户登录” → “用户”“户登”“登录”),查单字词(如“登”)会失败 - 索引字段需使用 utf8mb4 字符集,且排序规则为
utf8mb4_unicode_ci或utf8mb4_general_ci
如何正确创建支持中文搜索的 FULLTEXT 索引
假设留言板表叫 messages,内容字段为 content,你不能只写 ALTER TABLE messages ADD FULLTEXT(content) —— 这建立的是默认分词器索引,对中文无效。
正确做法是:
ALTER TABLE messages ADD FULLTEXT INDEX ft_content (content) WITH PARSER ngram;
注意三点:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 必须带
WITH PARSER ngram,否则还是走空格分词 - 如果表已存在大量数据,建索引会较慢,且建完需
OPTIMIZE TABLE messages触发分词重建 - 若字段原来有其他索引(如普通
INDEX),不影响全文索引共存,但查询时优化器未必总选它——得看SELECT ... MATCH() AGAINST()是否出现在 WHERE 中
AGAINST() 中的关键词写法和常见失效场景
AGAINST('登录' IN NATURAL LANGUAGE MODE) 是最常用写法,但中文下要注意:
- 不支持前缀通配(
'登录*'无效),ngram只做固定长度切分,不支持模糊扩展 - 短词(1 字)基本搜不到,除非调大
ngram_token_size(但会显著增加索引体积和降低精度) - 停用词仍起作用:MySQL 内置中文停用词表包含“的”“了”“在”等,即使启用
ngram,搜“的”也会被忽略 - 大小写不敏感,但全角/半角算不同字符(“ABC” ≠ “ABC”),留言里混用会导致漏匹配
调试建议:先用 SELECT * FROM information_schema.INNODB_FT_INDEX_CACHE 查当前内存缓存的分词结果(仅限最近插入/更新的行),确认“登录”是否真的被切成“登录”这个 token。
PHP/Node.js 查询时绕不开的细节
应用层调用时,别直接拼接用户输入进 AGAINST() —— 除了 SQL 注入风险,更关键的是:MySQL 全文检索对括号、引号、+ - ~ * 等符号有特殊语法含义。用户搜 node.js 或 c++ 会触发语法错误。
- PHP 中用
mysqli_real_escape_string()不起作用,得手动过滤:正则替换掉[()+~&|!:"\*]等全文语法字符,留字母、数字、汉字即可 - Node.js 的
mysql2同样不自动转义全文参数,需在AGAINST(?)绑定前清洗字符串 - 查不到结果时,别急着怀疑索引,先用
SELECT MATCH(content) AGAINST('关键词') AS score FROM messages LIMIT 5看 score 是否全为 0 —— 是的话,说明关键词压根没进倒排索引(停用词 or 未分词 or 字段为空)
ngram 分词本身无智能断词能力,“用户名密码”会被切成“用户”“户名”“名密”“密码”,所以实际效果依赖用户输入词是否恰好落在 ngram 切片上。真要高准召,得上 Elasticsearch 或 Meilisearch —— MySQL 全文索引只是低成本起步方案。

















