Mongo排序超32M问题解决

背景

事件列表分页查询时,报如下错:

说明:事件表中,如果事件如果聚合了很多告警,那这些事件的大小就会很大

问题分析

问题说明

MongoDB的 sort 操作是把数据拿到内存中再进行排序的,为了节约内存,默认给 sort 操作限制了最大内存为32M(mongo4.3以上版本是100M),当数据量超过限制后,就会抛异常。

如果排序或者查询时,命中了排序字段,那排序的时候,只需要将排序字段拉到内存中进行排序,如果未命中索引,则会将查询出来的所有文档拉到内存中进行排序。

代码分析

先来看下报错那一行的代码:

这里的排序,使用的是 lastDetectionTime 字段,来看下事件表建立的索引有哪些:

通过代码可以看到,查询条件只有主键ID列表,所以排序的时候,是不会走任何索引的。

 

解决方案

方案一:修改排序限制(不推荐)

将mongo排序限制改为100M。执行如下命令:

/usr/local/qingteng/mongodb/bin/mongo --host localhost --port 27017 -u qingteng -p fMElKUz36MY00ceg --authenticationDatabase admin
use amdin;
db.runCommand({
    setParameter: 1,
    "internalQueryExecMaxBlockingSortBytes": 104857600
});

执行效果:

 

方案二:排序字段创建索引(不推荐)

由于现在的查询条件不会命中组合索引 comId_lastDetectionTime,那只需要改下这个索引就可以命中。

删除组合索引comId_lastDetectionTime,新建组合索引lastDetectionTime_comId,命令:

db.ids_incident.createIndex({lastDetectionTime:-1, comId:1},{name:"lastDetectionTime_comId"})

 

方案三:修改查询条件

既然现有的查询条件不会命中组合索引 comId_lastDetectionTime,那就改下查询条件,让查询字段带上该组合索引。修改后的代码如下:

说明:最上面的IncidentQuery中是一定会包含comId、startTime、endTime的

 

posted @ 2022-06-20 17:04  仅此而已-远方  阅读(399)  评论(0编辑  收藏  举报