MySQL + ngram 最佳实践:轻量级中文 混合内容全文搜索方案
MySQL 的 FULLTEXT
配合 ngram
分词器,是一种 轻量但强大 的解决方案,适合处理中文、带符号文本(如 N3-2016-7语法7
)的全文搜索。
本文将介绍 MySQL + ngram 的最佳使用方式,包括:
✅ 配置环境
✅ 建立索引
✅ 查询语法
✅ 性能优化
✅ 常见问题
🧠 一、ngram 分词器简介
ngram(N-Gram)分词 是一种固定长度切词的方式。
例如对词语 N3-2016
:
-
ngram_token_size = 2 → 分为:
N3
、3-
、-2
、20
、01
、16
-
ngram_token_size = 3 → 分为:
N3-
、3-2
、-20
、201
、016
适合处理:
-
无自然分隔符的语言(如中文)
-
编码、编号、短词(如 SKU、题号、文章编号)
🛠️ 二、环境要求
-
✅ MySQL 5.7.6+(推荐 8.0+)
-
✅ 表引擎必须是 InnoDB
-
✅ 字符集推荐使用 utf8mb4
⚙️ 三、开启 ngram 分词功能
1. 查看当前系统设置
SHOW VARIABLES LIKE 'ngram_token_size';
默认值是 2
,你也可以全局修改:
SET GLOBAL ngram_token_size = 2; -- 修改为 2-gram
⚠️ 注意:修改后需 重启 MySQL 服务生效,且需 重建全文索引。
📑 四、表结构与索引设计
示例表:
CREATE TABLE t_question (
id INT PRIMARY KEY AUTO_INCREMENT,
question_content TEXT,
FULLTEXT (question_content) WITH PARSER ngram
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
✅
WITH PARSER ngram
是关键
✅ 推荐为TEXT
字段创建全文索引
若已有表:
ALTER TABLE t_question
ADD FULLTEXT(question_content) WITH PARSER ngram;
🔍 五、查询语法示例
1. 普通全文搜索(自动分词)
SELECT * FROM t_question
WHERE MATCH(question_content)
AGAINST('N3 2016' IN BOOLEAN MODE);
✅ 空格隔开多个关键词
✅ 可匹配如N3-2016-7语法7
2. 精准匹配(AND)
SELECT * FROM t_question
WHERE MATCH(question_content)
AGAINST('+N3 +2016' IN BOOLEAN MODE);
+
表示必须包含
3. 模糊匹配(带通配符)
SELECT * FROM t_question
WHERE MATCH(question_content)
AGAINST('N3* 2016*' IN BOOLEAN MODE);
⚠️ 通配符仅在 BOOLEAN MODE
下部分生效,ngram
本身已实现了前缀模糊能力。
4. 预处理数据以提高匹配率
将符号(如 -
、/
)替换为空格以便更好分词:
UPDATE t_question
SET question_content = REPLACE(question_content, '-', ' ');
也可以在搜索时处理关键词:
SELECT * FROM t_question
WHERE MATCH(question_content)
AGAINST(REPLACE('N3-2016-7', '-', ' ') IN BOOLEAN MODE);
🚀 六、性能优化建议
优化项 | 建议 |
---|---|
✅ 字段类型 | 使用 TEXT 类型,不建议用 VARCHAR 超过 767 字节 |
✅ 字符集 | 使用 utf8mb4 ,兼容所有字符 |
✅ 查询语法 | 使用 BOOLEAN MODE 支持更多操作符 |
✅ 排序限制 | 查询加 LIMIT 、避免 ORDER BY MATCH() 造成排序慢 |
✅ 表数据变更 | 更新/删除后需注意索引同步,定期优化表(OPTIMIZE TABLE ) |
🧱 七、MySQL ngram 与其他方案对比
方案 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
LIKE %keyword% | 简单 | 性能差 | 小数据量 |
FULLTEXT (默认) | 快、支持英文 | 不支持中文 | 英文搜索 |
FULLTEXT + ngram | 支持中文和符号、轻量 | 精度略低于 NLP 分词 | 中小项目、编码类内容搜索 |
Elasticsearch | 强大、支持复杂分析 | 运维成本高 | 搜索引擎、大数据量 |
Jieba / HanLP | 可控性强、精度高 | 不支持数据库原生索引 | NLP 应用、离线分析 |
🧩 八、常见问题 FAQ
❓1. 中文搜索无结果?
请确认是否:
-
使用了
WITH PARSER ngram
-
字符集为
utf8mb4
-
数据和查询内容一致
-
ngram_token_size
合适
❓2. 如何支持带符号内容(如 N3-2016
)?
使用 ngram 可将其切割为 N3
、3-
、-2
等小词组,实现模糊匹配。
❓3. 索引是否生效?
可用以下命令查看全文索引:
SHOW INDEX FROM t_question;
也可 EXPLAIN 查询看是否使用了 FULLTEXT
索引。
✅ 九、最佳实践总结
项目 | 推荐做法 |
---|---|
✅ 字段 | TEXT 类型字段建全文索引 |
✅ 索引 | 使用 WITH PARSER ngram |
✅ 查询 | 使用 AGAINST + BOOLEAN MODE + 空格关键词 |
✅ 兼容性 | 使用 MySQL 8.0+,InnoDB 引擎 |
✅ 性能 | 合理使用 LIMIT,避免排序瓶颈 |
✅ 文本规范化 | 去除无意义符号、统一大小写,提升匹配率 |
用 MySQL 做中文和混合搜索?别忘了加上
ngram
,轻量、原生、好用!