MySQL + ngram 最佳实践:轻量级中文 & 混合内容全文搜索方案

MySQL 的 FULLTEXT 配合 ngram 分词器,是一种 轻量但强大 的解决方案,适合处理中文、带符号文本(如 N3-2016-7语法7)的全文搜索。

本文将介绍 MySQL + ngram 的最佳使用方式,包括:

✅ 配置环境
✅ 建立索引
✅ 查询语法
✅ 性能优化
✅ 常见问题


一、ngram 分词器简介

ngram(N-Gram)分词 是一种固定长度切词的方式。
例如对词语 N3-2016

  • ngram_token_size = 2 → 分为:N33--2200116

  • ngram_token_size = 3 → 分为:N3-3-2-20201016

适合处理:

  • 无自然分隔符的语言(如中文)

  • 编码、编号、短词(如 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 可将其切割为 N33--2 等小词组,实现模糊匹配。


❓3. 索引是否生效?

可用以下命令查看全文索引:

SHOW INDEX FROM t_question;

也可 EXPLAIN 查询看是否使用了 FULLTEXT 索引。


✅ 九、最佳实践总结

项目 推荐做法
✅ 字段 TEXT 类型字段建全文索引
✅ 索引 使用 WITH PARSER ngram
✅ 查询 使用 AGAINST + BOOLEAN MODE + 空格关键词
✅ 兼容性 使用 MySQL 8.0+,InnoDB 引擎
✅ 性能 合理使用 LIMIT,避免排序瓶颈
✅ 文本规范化 去除无意义符号、统一大小写,提升匹配率

用 MySQL 做中文和混合搜索?别忘了加上 ngram,轻量、原生、好用!

你可能感兴趣的:(其他,mysql,搜索)