百万级记录下MongoDB带match和sort的聚合查询过慢优化问题
MongoDB聚合查询慢优化方案
问题根因
你的查询慢的核心原因是:当前执行逻辑优先用了searches单字段索引,匹配到所有符合条件的文档后,需要在内存中对这部分文档的hour字段做排序,当匹配的文档量级达数十万以上时,排序开销会被急剧放大,这就是加了$sort后耗时暴涨的核心原因,移除$sort后仅需返回匹配结果,无需排序操作,因此速度快。
优化方案
1. 调整复合索引结构,启用覆盖查询
你提到已经创建了searches+hour的复合索引,但大概率是索引结构和查询模式不匹配导致没有生效。
请按如下命令重建复合索引:
db.tweets.createIndex({searches: 1, hour: -1})
该索引完全匹配你的查询逻辑:
- 前缀
searches:1正好匹配$match阶段的过滤条件,可以快速定位所有符合条件的条目 - 后缀
hour:-1正好匹配$sort阶段的倒序排序要求,索引本身已经按hour倒序排列,查询时不需要额外做内存排序 - 你的
$project阶段仅返回_id、searches、hour三个字段,所有字段都包含在上述复合索引中,MongoDB可以直接从索引读取结果,不需要访问原始集合数据,即覆盖查询,效率极高
优化后该查询的耗时可以降到毫秒级。
2. 验证执行计划
优化后可以执行如下命令查看执行计划,确认优化生效:
db.tweets.explain("executionStats").aggregate([/* 你的聚合语句 */])
正常优化后的执行计划不会出现SORT阶段,扫描的文档数等于1(直接返回索引排序后的第一条结果)。
内容的提问来源于stack exchange,提问作者Martin Ratinaud
相关产品推荐
相关产品推荐

