核心事实
掘金开发者社区近日published了一篇关于MySQL中文搜索性能的实测报告。作者在1核2G服务器、50万行中文语料上对比了LIKE、ngram全文索引自然语言模式与布尔模式的查询表现。核心硬信息:MySQL 5.7.6起内置ngram解析器,8.0文档14.9.8节明确记录,无需外部ES集群即可实现中文全文搜索。建索引会重建聚簇索引并增加存储空间,50万行表data_length从213MB增至311MB;加索引操作在10万行表耗时52.8秒。
- 无命中词查询:LIKE耗时886ms,ngram自然语言与布尔模式均为0ms(LIMIT 20场景)
- 2字高频词"缓存":LIKE 684ms → 自然语言模式150ms(快4.5倍),布尔模式215ms
- 4字词"消息队列":LIKE 785ms → 自然语言模式323ms,布尔模式1710ms(比LIKE慢2.2倍)
性能表现与关键反差
最意外的数据出现在长词查询上:Boolean模式搜4字短语"消息队列"耗时1710ms,是LIKE全表扫描(785ms)的2.2倍,更是自然语言模式(323ms)的5.3倍。根本原因在于Boolean模式下中文查询会转为ngram短语搜索——先查出所有ngram片段(消息、息队、队列)的文档,再逐条校验片段是否连续出现。50万行中16万条命中时,每条都需要读取位置信息验证连续性,单核环境下成本反超简单全扫。
另一组风险数据体现在误召回率:作者用"数据库连接池"测试,LIKE与布尔模式均精确命中196892条,而自然语言模式(默认模式)命中379058条,虚高92%。作者统计发现182166条(48%)正文根本未出现完整短语,仅因包含"数据"“库"“连接"等片段被召回。
更冷门的限制是:单字查询完全失效。因ngram_token_size默认为2,索引中不存在单字token,搜"缓"字将返回0结果。修改参数需重启服务,且影响全库所有ngram索引。
场景适配对比
| 查询类型 | LIKE全扫描 | ngram自然语言模式 | ngram布尔模式 |
|---|---|---|---|
| 无命中词(Long) | 886ms | 0ms | 0ms |
| 2字高频词 | 684ms | 150ms | 215ms |
| 4字短语 | 785ms | 323ms | 1710ms(反慢2.2倍) |
| 单字查询 | 命中253889 | 0 | 0 |
| 误召回率 | 0% | 48% | 0% |
注:测试环境为1核2G服务器,50万行中文语料,LIMIT 20分页查询;布
适配建议
适合立刻上车的场景:后台管理系统的内容搜索框、50万级以内数据量、查询词以2-4字整词为主、能接受精确匹配要求的业务。必须遵守两条纪律:
- 查询词必须用双引号包裹走布尔模式(与LIKE结果严格等价)
- 禁用默认自然语言模式,否则近半结果为"沾边但不是"的误召回
该再等等/换方案的场景:
- 搜索是产品主路径且查询词长度>5(Boolean短语校验成本反噬性能)
- 需要单字检索(如通讯录搜姓氏"张”)
- 对结果精确性要求极高无法接受分词召回
- 内存≤2GB且可能执行长词Boolean查询(实测触发OOM Killer)
写在最后
MySQL原生ngram索引填补了中文搜索的基础设施空白,但其语义处理逻辑与英文全文检索差异显著。对于工单系统等中低频后台搜索,一个ALTER TABLE ADD FULLTEXT即可替代轻量级ES集群;一旦涉及用户侧高频搜索、长尾词或复杂相关性排序,ES提供的倒排索引优化与分词能力仍不可替代。选择标准不在成本高低,而在查询模式与业务容忍度是否匹配技术特性。
