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)])