mongodb聚合排序的一个巨坑

现象:

mongodb cpu动不动要100%,如下图

分析原因:

查看慢日志发现,很多条这样的查询,一直未执行行完成,占用大量的CPU

go 复制代码
[
 {
 $match: {
 "tags.taskId": "64dae0a9deb52d2f9a1bd71e",
 grnty: "minute",
 "tags.type": "task",
 "tags.taskRecordId":
 "64e5c004133738231bc36906",
 },
 },
 {
 $sort: {
 _id: -1,
 },
 },
 {
 $limit: 5,
 },
 {
 $unwind: "$ss",
 },
 {
 $group: {
 _id: "$ss.vs.inputQps",
 qps: {
 $avg: "$ss.vs.inputQps",
 },
 },
 },
]

查看程序里面有一段聚合的代码

go 复制代码
Criteria criteria = new Criteria();
tags.forEach((k,v)->{
    String format = String.format(TAG_FORMAT, k);
    criteria.and(format).is(v);
});
criteria.and(MeasurementEntity.FIELD_GRANULARITY).is(Granularity.GRANULARITY_MINUTE);
MatchOperation match = Aggregation.match(criteria);
SortOperation sort = Aggregation.sort(Sort.by(Sort.Direction.DESC, "_id"));
LimitOperation limit = Aggregation.limit(5);
UnwindOperation unwind = Aggregation.unwind("ss", false);
GroupOperation group = Aggregation.group().avg("ss.vs.inputQps").as("qps");
Aggregation aggregation = Aggregation.newAggregation(match, sort, limit, unwind, group);

看一下这个代码也没有多大问题,但是就是执行很慢很慢,于是我explain这条语句,发现是先执行全集合sort 然后再match的,理论上应该是先match,然后再执行针对查询的结果做sort的

已经使用了 match 和 sort 操作来筛选和排序文档。仍然对整个集合进行了排序?

这可能是由于 MongoDB 的查询优化器在执行查询时做出的决策。在 MongoDB 中,查询优化器会尝试根据查询计划和索引来优化查询性能。在某些情况下,优化器可能会选择在 match 操作之后对整个集合进行排序,而不仅仅是对 match 操作筛选出的文档进行排序。这可能是因为优化器认为在整个集合上进行排序的成本更低,或者由于其他优化策略。如果你希望只对 $match 操作筛选出的文档进行排序,可以尝试使用索引来优化查询。确保你的查询条件和排序字段都有适当的索引,这样可以帮助优化器做出更好的决策,以便只对筛选结果进行排序。

解决方案

在这种情况下,你可以尝试创建一个复合索引,包含筛选条件和排序字段。例如,你可以创建一个包含 "tags.taskId","grnty","tags.typ","tags.taskRecordId","_id" 字段的复合索引。这样,MongoDB 在执行查询时可以使用该索引来加速筛选和排序操作。

总结

为了只对筛选结果进行排序,你可以尝试以下步骤:

  1. 创建一个复合索引,包含筛选条件和排序字段。

  2. 确保查询条件和排序字段在索引中的顺序与聚合管道中的顺序一致。

  3. 使用 explain() 方法来查看查询的执行计划和索引使用情况,以便进行优化。

相关推荐
updayday8543 分钟前
客户附件不该发往旧邮箱,如何在发送前拦截 - Ping64 邮件安全管控
大数据·网络·数据库·安全·智能路由器
倔强的石头_9 分钟前
连接异常排障手册:拒连、超时、认证失败、空闲断开
数据库
lhbweilai31 分钟前
QT(了解各个控件和布局)上
数据库·qt
莫晓燚1 小时前
搭建Redis 主从复制---实战
数据库·redis·缓存
灵晔君1 小时前
【MySQL】数据库基础
数据库·mysql·adb
香蕉大香蕉(06敬畏市场)2 小时前
MySQL 单点详解(03)
java·数据库·mysql·面试·八股·大厂实习
赤生云电竞2 小时前
云游戏边缘节点部署:机房选址与网络拓扑优化实践——接入延迟、VXLAN与GPU虚拟化选型
数据库·游戏
Y003 小时前
PostgreSQL 权限管理踩坑记:从 42501 到默认权限和 RLS
数据库·postgresql
呆萌很3 小时前
达梦(DM8)数据库常用SQL
数据库·sql
跟太阳说早安3 小时前
极简数据库SQL
数据库·sql