mongo mysql 聚合性能_记录一次 MongoDB aggregate的性能优化经历

mongod(ZN5mongo15printStackTraceERSo+0x41) [0x55bd3a2dd321]

mongod(ZN5mongo29reportOutOfMemoryErrorAndExitEv+0x84) [0x55bd3a2dc954]

mongod(ZN5mongo12mongoReallocEPvm+0x21) [0x55bd3a2d22b1]

mongod(ZN5mongo11BufBuilderINS21SharedBufferAllocatorEE15growreallocateEi+0x83) [0x55bd38981833]

mongod(ZN5mongo3rpc17OpMsgReplyBuilder22getInPlaceReplyBuilderEm+0x80) [0x55bd39d4b740]

mongod(+0xAB9609) [0x55bd389be609]

mongod(+0xABBA59) [0x55bd389c0a59]

下面是聚合的脚本,很简单,就是统计某辆车多个状态码的最新值(通过$first实现)。

db.getCollection("vinMsgOut").aggregate([

{"$match": {"vinCode": "LSGKR53L3HA149563"}},

{"$sort": {"postTime" : -1}},

{"$group": {

"_id": "$messageType",

"resultValue": {"$first": "$resultValue"}

}

}

],{ allowDiskUse: true })

第一反应是增加过滤条件及增加索引。

结合业务,增加时间条件过滤,将$match改为:

{"$match": {"vinCode": "LSGKR53L3HA149563", "createTime": {$gt: ISODate("2020-03-01T06:30:12.038Z")}}}

再分别为vinCode和createTime创建索引,执行,依旧是6秒多。。。

将$sort的字段改成索引字段createTime,

{"$sort": {"createTime" : -1}}

再次执行,时间依旧是6秒多。。。

由于系统可分配内存有限,存储引擎已经默认是最快的wiredTiger,磁盘也没法更给力,只能从业务上再着手。考虑到这些最新状态的出现,一般都是同一个时间段,状态码只有几百个,如果sort之后,只从pipe取其中一部分进行group,会不会更快些?带着这个疑问,我加了一条limit。

db.getCollection("vinMsgOut").aggregate([

{"$match": {"vinCode": "LSGKR53L3HA149563", "createTime": {$gt: ISODate("2020-03-01T06:30:12.038Z")}}},

{"$sort": {"createTime" : -1}},

{"$limit": 1000},

{"$group": {

"_id": "$messageType",

"resultValue": {"$first": "$resultValue"}

}

}

],{ allowDiskUse: true })

结果是秒回!

去掉$match中的createTime条件,依旧秒回!这是否意味着createTime索引并没有起作用?带着疑问,将createTime索引删掉,返现时间变成5秒,所以createTime的索引是有用的,用在$sort而已。综上,完成了整个查询的优化,总结下来就是:

$match条件需要增加索引,如果是多个,最好用组合索引;

$sort的字段也需要增加索引;

$group的_id也需要增加索引;

limit可以大幅度降低时耗。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MongoDB中,可以使用MongoTemplate进行聚合查询以获取最新的一条数据。以下是一个例子: ```java // 创建聚合管道操作列表 List<AggregationOperation> operations = new ArrayList<>(); // 添加聚合操作,按照时间降序排序并取第一条数据 operations.add(Aggregation.sort(Sort.Direction.DESC, "timestamp")); operations.add(Aggregation.limit(1)); // 执行聚合查询 Aggregation aggregation = Aggregation.newAggregation(operations); AggregationResults<Document> result = mongoTemplate.aggregate(aggregation, "collectionName", Document.class); // 获取查询结果 List<Document> resultList = result.getMappedResults(); Document latestData = resultList.get(0); // 打印最新的一条数据 System.out.println(latestData); ``` 在上述代码中,首先创建一个聚合管道操作列表,并添加了两个聚合操作。sort操作用于按照时间字段降序排序,limit操作用于限制结果只返回一条数据。 然后,使用MongoTemplate的aggregate方法执行聚合查询。其中,Aggregation.newAggregation方法用于创建Aggregation对象,指定了要执行的聚合操作列表和结果的类型。mongoTemplate.aggregate方法执行聚合查询,并将结果存储在AggregationResults对象中。 最后,通过AggregationResults对象的getMappedResults方法获取查询结果的列表,并获取其中的第一条数据作为最新的一条数据。 请注意,上述代码中的"collectionName"需要替换为实际的集合名称。此外,还需要根据实际情况修改代码以适应具体的数据结构和字段名。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值