问题:
执行以下查询出错:"Executor error during find command :: caused by :: Sort operation used more than the maximum 33554432 bytes of RAM. Add an index, or specify a smaller limit.",
db.getCollection('notice') .find({ "field1" : aaa}) .sort({"sortField1" : -1, "sortField2" : -1})
原因:
mongodb在执行排序时,首先尝试使用索引中的指定顺序检索文档,如果没有可用索引,则会将所有文档加载到内存中排序,默认情况下,可用内存的配置为32M,超过该值时就会遇到以上错误;
使用如下命令可以查看该配置:
// 注意,在admim集合中执行 db.runCommand( { getParameter : 1, "internalQueryExecMaxBlockingSortBytes" : 1 } )
解决方法:
1,既然首先查找索引,那么性能最友好的方式便是在排序字段上加索引;
// 创建索引 createIndex db.getCollection('notice').createIndex( { 'sortField': 1 } ) // 推荐用 ensureIndex db.getCollection('notice').ensureIndex( { 'sortField': 1 } )
2,也可修改配置,提高可用内存;
db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes: 335544320})
3,使用聚合命令排序,聚合命令具有最大的内存使用配置,在处理大型数据集时,可以添加{ allowDiskUse: true}的option,将中间处理过程输出到磁盘临时文件进行处理,当然这个性能会差
db.getCollection('notice').aggregate( [ { $sort : { 'sortField': 1} } ], { allowDiskUse: true } )
其他知识点:
Sort Operations
https://docs.mongodb.com/manual/reference/limits/#Sort-Operations
Sort and Index Use
https://docs.mongodb.com/manual/reference/method/cursor.sort/#sort-index-use
MongoDB可以从包含排序字段的索引中获得排序操作的结果。如果排序使用与查询谓词相同的索引,则MongoDB可以使用多个索引来支持排序操作。
如果MongoDB无法使用一个或多个索引来获取排序顺序,则MongoDB必须对数据执行阻塞排序操作。阻塞排序表示MongoDB必须使用并处理所有输入文档,直到返回结果。阻塞排序不会阻塞集合或数据库上的并发操作。