Executor error during find command: OperationFailed: Sort operation used more than the maximum ***

探讨MongoDB在执行大规模数据排序时遇到的内存溢出问题,介绍如何通过调整配置和创建索引来优化查询性能,避免Executor错误。

Query failed with error code 96 and error message 'Executor error during find command: OperationFailed: Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit.' on server

刚开始还以为是查询得到的内容比较大,所以指定字段即指定查询返回的字段,我用的是 Spring data mongo 的 query(),大致方法如下:

 Query query = Query.query(new Criteria());
 PageRequest pageRequest=new PageRequest(pageNumber - 1, pageSize);
 query.addCriteria(Criteria.where("fillStatus").gte(10));
 query.skip(pageRequest.getOffset()).limit(pageSize).with(new Sort(Sort.Direction.DESC, "createTime"));
 long totalCount=this.mongoDao.count(query,HealthQues.class);
 int totalPage=0;
 if(totalCount%pageSize==0){
     totalPage=Integer.parseInt(totalCount/pageSize+"");
 }else{
     totalPage=Integer.parseInt(totalCount/pageSize+"")+1;
 }
//指定返回字段
query.fields().include("id");
query.fields().include("memberId");

等等、、、这里指定一个就返回一个,指定俩个就返回两个。

List<HealthQues> healthQuesList=this.mongoDao.find(query,HealthQues.class);//程序运行到这里报错!结果查询到仍然报错!!!

原因比较明确:Sort operation used more than the maximum 33554432 bytes of RAM.,33554432 bytes算下来正好是32Mb,而mongodb的sort操作是把数据拿到内存中再进行排序的,为了节约内存,默认给sort操作限制了最大内存为32Mb,当数据量越来越大直到超过32Mb的时候就自然抛出异常了!解决方案有两个思路,一个是既然内存不够用那就修改默认配置多分配点内存空间;一个是像错误提示里面说的那样创建索引。

首先说如何修改默认内存配置,在Mongodb命令行窗口中执行如下命令即可:

db.adminCommand({setParameter:1, internalQueryExecMaxBlockingSortBytes:335544320}) //不推荐使用

我直接把内存扩大了10倍,变成了320Mb。从这里可以看出,除非你服务器的内存足够大,否则sort占用的内存会成为一个严重的资源消耗!

然后是创建索引,也比较简单:

db.yourCollection.createIndex({<field>:<1 or -1>})  //只执行这句就能解决bug  注意不能直接复制粘贴,要根据集合编写语句。
db.yourCollection.getIndexes()  //查看当前collection的索引

其中1表示升序排列,-1表示降序排列。索引创建之后即时生效,不需要重启数据库和服务器程序,也不需要对原来的数据库查询语句进行修改。创建索引的话也有不好的地方,会导致数据写入变慢,同时Mongodb数据本身占用的存储空间也会变多。不过从查询性能和服务器资源消耗这两方面来看,通过创建索引来解决这个问题还是最佳的方案!

### 关于 `mongo::executor::ConnectionPool::SpecificPool::updateStatelnLock` 的分析 在 MongoDB 中,`mongo::executor::ConnectionPool` 是用于管理网络连接池的核心组件之一。具体到子类 `SpecificPool` 和其方法 `updateStatelnLock`,该函数主要用于更新特定线程或操作状态下的统计信息,并可能涉及锁机制以确保并发安全性。 以下是关于此功能的一些关键点: #### 方法的功能描述 `updateStatelnLock` 函数的主要目的是在持有锁的情况下更新与连接池相关的统计数据[^1]。这通常包括但不限于以下内容: - 更新当前活动连接的数量。 - 跟踪已创建和销毁的连接总数。 - 维护超时或其他异常情况的相关计数器。 由于涉及到锁 (`lnLock`),可以推测该方法会在多线程环境中被调用,因此需要通过加锁来防止数据竞争问题[^2]。 #### 可能的代码结构 基于常见的设计模式以及 MongoDB 源码中的惯例,下面是一个假设性的伪代码实现示例: ```cpp void mongo::executor::ConnectionPool::SpecificPool::updateStatelnLock() { std::lock_guard<stdx::mutex> lock(_mutex); // 加锁以保护共享资源 // 增量更新某些统计指标 _stats.activeConnections++; _stats.totalCreatedConnections++; // 如果存在其他条件,则进一步调整统计值 if (_someCondition) { _stats.timeoutCount++; } } ``` 在此代码片段中: - `_mutex` 是一个互斥锁对象,用来同步访问共享变量 `_stats`。 - `_stats` 表示存储各种运行时统计信息的数据结构,可能是某种自定义类实例或者标准库容器 (如 `std::map`)。 需要注意的是实际源码可能会更加复杂,包含更多细节处理逻辑[^3]。 #### 调试建议 当尝试定位与此方法有关的问题时,可以从以下几个方面入手: 1. **日志记录**:检查是否有足够的调试信息输出至日志文件中,特别是围绕着每次调用前后发生的事件序列。 2. **性能瓶颈检测**:利用工具测量获取/释放锁所需时间是否过长从而影响整体效率。 3. **竞态条件排查**:验证是否存在未预期的行为比如死锁现象发生。 以上是对您所提到主题的一个概括总结;如果希望获得更精确的信息则需深入研究官方文档或是直接查阅最新版本的MongoDB开源项目仓库内的对应部分。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值