Query failed with error code 17144 and error message 'Executor error: Overflow sort stage buffered data usage of 33594336 bytes exceeds internal limit of 33554432 bytes' on server ip:27017; nested exception is com.mongodb.MongoQueryException: Query failed with error code 17144 and error message 'Executor error: Overflow sort stage buffered data usage of 33594336 bytes exceeds internal limit of 33554432 bytes' on server ip:27017
这个问题真的是困扰我很久才找到,主要不是这个问题有多难理解,而是代码里我们针对异常都trycatch打的自己的日志,猜不透是什么原因导致的,后来网上找了个工具类,在catch里打印了堆栈异常的相关信息才发现这个mongodb的错误
这个错误是指,你的查询里指定了排序,mongodb排序的时候如果排序字段没有索引会把全部数据都读到内存里,默认有个32M的大小限制(为了节约内存,默认给sort操作限制了最大内存为32Mb,当数据量越来越大直到超过32Mb的时候就自然抛出异常了!)
所以有两种解决方案
解决方案:
1)修改默认内存,
db.adminCommand({setParameter:1, internalQueryExecMaxBlockingSortBytes:335544320}) //不推荐使用
2)创建索引 db.yourCollection.createIndex({<field>:<1 or -1>})
参考
原文链接:https://blog.csdn.net/u010411264/article/details/79583305
这里把握从网上找的打印堆栈信息的工具类贴出来,有所改动,特别是把具体错误原因输出到日志里了:
package com.taikang.obs.common.utils;
/**
* @Author: LiuYan
* @Description:
* @Date: Created in 12:22 2020/1/8
*/
public class ExcpUtil {
//打印异常堆栈信息
public static String getStackTraceString(Throwable ex) {//(Exception ex) {
StackTraceElement[] traceElements = ex.getStackTrace();
StringBuilder traceBuilder = new StringBuilder();
traceBuilder.append(ex.getMessage());
traceBuilder.append("\n");
if (traceElements != null && traceElements.length > 0) {
for (StackTraceElement traceElement : traceElements) {
traceBuilder.append(traceElement.toString());
traceBuilder.append("\n");
}
}
return traceBuilder.toString();
}
//构造异常堆栈信息
public static String buildErrorMessage(Exception ex) {
String result;
String stackTrace = getStackTraceString(ex);
String exceptionType = ex.toString();
String exceptionMessage = ex.getMessage();
result = String.format("%s : %s \r\n %s", exceptionType, exceptionMessage, stackTrace);
return result;
}
}
使用范例:
public void createAutoInsReport(String nowDateString, String fileName) throws IOException {
int count = 0;
//文件名以当天时间为准,对应当天流水记录的报表数据
File file = new File(path + fileName);
FileWriter fw = null;
BufferedWriter bw = null;
try {
fw = new FileWriter(file);
bw = new BufferedWriter(fw);
//先写当天导入的数据,全部都提交到报表中做统计
count = writeCurrentDayInsertData(nowDateString, bw);
log.info("报表中当天导入的数据有" + count + "条已导入");
//再把之前导入的但是当天才处理完成的数据写入报表文件
count = writePastDayInsertData(nowDateString, bw) + count;
} catch (Exception e) {
log.info("车险报表存在问题" + ExcpUtil.getStackTraceString(e));
} finally {
if (bw != null) bw.close();
if (fw != null) fw.close();
}
log.info("今天推送了" + count + "条数据到车险报表");
File okFile = new File(path + (fileName.replace(".txt", ".ok")));
okFile.createNewFile();
}