MongoDB百万级记录场景下索引不生效问题排查求助
MongoDB文本索引查询耗时与无索引一致问题排查
环境信息
- 远程服务器:部署在DigitalOcean的Ubuntu 20.04实例,配置为1vCPU、1GB内存、25GB存储,MongoDB运行在该实例上
- 本地机器:MacOS系统,运行Docker化的Node.js Express服务,通过该服务对数据库集合执行搜索操作
测试前置准备
- 数据库共创建两个集合:已创建索引的
PartnerModelIndex、未创建索引的PartnerModel
- Node.js服务共创建2个API路由,其中1个路由专门用于查询已建索引的集合

- 两个集合各写入100万条测试文档,单条文档字段参数如下:
title:单条文档该字段约20-30个单词description:单条文档该字段约5000-6000字符
问题现象
通过title和description字段搜索不存在的字符串时,已建索引集合和无索引集合的查询执行时间完全一致:
- 已建索引集合查询耗时:

- 无索引集合查询耗时:

可能原因及排查方案
- 索引类型不匹配
你创建的可能不是适配文本搜索的联合文本索引,比如误建了普通单字段索引、前缀索引,而非针对title+description的text类型索引,这种情况下MongoDB执行文本搜索时无法命中索引,仍会执行全表扫描,耗时自然和无索引场景一致。
排查方式:在MongoDB Shell中执行db.PartnerModelIndex.getIndexes(),确认存在key: { title: "text", description: "text" }配置的索引。 - 查询语法错误导致索引失效
MongoDB的文本索引仅支持$text+$search的查询语法,如果你使用的是$regex正则匹配、title:/xxx/的模糊匹配语法,都无法命中文本索引,会强制触发全集合扫描,导致两种场景耗时无差异。
正确的全文搜索语法示例:
db.PartnerModelIndex.find({ $text: { $search: "目标搜索字符串" } })
- 索引未成功加载到内存
你的服务器仅配置1GB内存,扣除系统、MongoDB基础进程占用外,可用内存可能不足以容纳完整的文本索引,MongoDB查询时需要从磁盘读取索引数据,若该场景下读取索引的磁盘IO耗时与全表扫描读取集合数据的耗时接近,也会出现两者耗时相近的情况。
排查方式:执行db.collection.stats()查看索引大小,确认索引总大小小于MongoDB可用内存。 - 耗时统计包含额外开销
你统计的是从本地Docker服务发起请求到收到响应的全链路耗时,其中网络往返开销、Node.js服务本身的处理开销可能远大于MongoDB实际查询耗时,掩盖了有索引和无索引的查询耗时差。
排查方式:直接在远程服务器的MongoDB Shell中执行查询,通过explain("executionStats")返回的executionTimeMillis字段确认MongoDB实际执行耗时。
内容的提问来源于stack exchange,提问作者spatak
相关产品推荐
相关产品推荐

