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的
知识改变世界
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了