MongoDB排序異常


com.mongodb.MongoQueryException: 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 

調用方法如下:

 protected <T> List<T> findByPage(Class clazz, String collectionName, int pageNum, int pageSize, String queryStr, String orderKey, Boolean asc){
        if(StringUtils.isBlank(orderKey)){
            orderKey = "createTime";
        }
        try {
            Iterator<Class> articleMainList = (Iterator<Class>) mongodbService.getJongo()
                    .getCollection(collectionName).find(queryStr).sort("{" + orderKey + ":" + (asc ? "1" : "-1") + "}")
                    .skip((pageNum - 1) * pageSize).limit(pageSize).as(clazz);
            return IteratorUtils.toList(articleMainList);
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

  

 

原因比較明確: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}) //不推薦使用

在 mongo 使用過程中遇到了一個問題,需求就是要對mongo 庫中查詢到數據進行分頁,mongo庫我們知道都會存儲大容量的數據,剛開始使用的 skip 和 limit 聯合使用的方法,來達到截取所需數據的功能,這種方法在庫里數據容量小的情況下完全可以勝任,但是如果庫里數據多的話,上面兩個方法就不好使了,就像題目中那個錯誤,這時會報一個 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.' 
按照錯誤提示,知道這是排序的時候報的錯,因為 mongo 的 sort 操作是在內存中操作的,必然會占據內存,同時mongo 內的一個機制限制排序時最大內存為 32M,當排序的數據量超過 32M,就會報上面的這個錯,解決辦法就像上面提示的意思,一是加大 mongo 的排序內存,這個一般是運維來管,也有弊端,就是數據量如果再大,還要往上加。另一個辦法就是加索引,這個方法還是挺方便的。創建索引及時生效,不需要重啟服務。 
創建索引也不難, 
db.你的collection.createIndex({“你的字段”: -1}),此處 -1 代表倒序,1 代表正序; 
db.你的collecton.getIndexes(); 
這兩個語句,第一個是添加索引,第二個是查詢索引,如果查看到你剛才添加的那個索引字段,就說明索引添加成功了。這時候在你的程序里再運用 sort 方法的話,這樣就不會報錯而且速度很快。 
添加索引會帶來一定的弊端,這樣會導致數據插入的時候相對之前較慢,因為索引會占據空間的。綜上考慮,根據實際情況判斷采用合適的方法。 
案例: 
mongodb執行如下語句

db.three_province_poi_v9.find({ "sum_n.sum_4_x":{ $gt:0} } ).sort({"sum_n.sum_4_x":-1}) 

報錯如下:

Error: error: {
    "ok" : 0,
    "errmsg" : "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.",
    "code" : 96,
    "codeName" : "OperationFailed"
}

  

按照前面所述:執行

db.three_province_poi_v9.createIndex({"sum_n.sum_4_x": -1})

  

則在執行語句,即可得到結果

python 下pymongo執行

db_first.three_province_poi_v9.find({"sum_n.sum_4_x":{ "$gt":0} } ).sort([("sum_n.sum_4_x",-1)])

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM