描述:
Request processing failed; nested exception is org.springframework.data.mongodb.UncategorizedMongoDbException: Query failed with error code 17144 and error message 'Plan executor error during find: Overflow sort stage buffered data usage of 33554768 bytes exceeds internal limit of 33554432 bytes' on server mongodb:27017; nested exception is com.mongodb.MongoQueryException: Query failed with error code 17144 and error message 'Plan executor error during find: Overflow sort stage buffered data usage of 33554768 bytes exceeds internal limit of 33554432 bytes' on server mongodb:27017
请求处理失败; 嵌套的异常是org.springframework.data.mongodb.UncategorizedMongoDbException:查询失败,错误代码17144,错误消息“查找期间计划执行器错误:服务器上mongodb:27017上的33554768字节的溢出排序阶段缓冲的数据使用量超过了33554432字节的内部限制” ; 嵌套异常为com.mongodb.MongoQueryException:服务器mongodb:27017在查询中失败,错误代码为17144,错误消息“查找期间计划执行程序错误:33554768字节的溢出排序阶段缓冲的数据使用量超过了33554432字节的内部限制”
原因:
在使用 db.collection.find({}).sort({"update_time" : "-1"}).skip(20000).limit(20); 这种方式查询的时候,mongoDB先是按照字段"update_time"全库排序,然后再跳过前面20000条记录,再返回20条数据;其中skip操作需要将文档全部加载到缓存中,然后再抛弃这部分数据,而mongDB的缓存是有大小限制的,超过限制就会报错;
解决:
一:给排序字段添加索引:
给对应的排序条件添加索引,然后skip操作就可以在索引上完成,然后不需要再加载全文档到缓存中;
db.collection.createIndex({"update_time" : -1}, {background : true});
二:修改缓存大小限制:
use admin db.runCommand({getParameter : 1, "internalQueryExecMaxBlockingSortBytes" : 1}); // 查询当前缓存区大小,默认是32M db.runCommand({setParameter : 1, internalQueryExecMaxBlockingSortBytes : 335544320}); // 将当前缓存区大小设置为320M 此命令仅在3.0 +版之后支持
三:使用 aggregate() 方法查询:
在执行一个更大规模排序时,即使已经加了索引依然超过限制,可以使用aggregate()方法的 allowDiskUse 参数设置将数据写到临时文件进行排序;
//语法:pipeline -> array, options -> document db.collection.aggregate(pipeline, options) //举例: db.getCollection("topic_log").aggregate( [ {$sort : {"createTime" : -1}} ], {allowDiskUse: true} );