2023-02-05|閱讀時間 ‧ 約 3 分鐘

MongoDB 無法排序:Sort operation used more than the maximum 33554

當使用以下語法對 Log 這個 Collection 依照 CreateTime 做倒序查詢
db.Log.find().sort({CreateTime: -1})
MongoDB 回傳了以下 Error Msg
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"
}

發生原因

MongoDB 在排序時會將資料全部載入記憶體,之後在記憶體中進行排序,而預設開放給排序的記憶體只有 32 MB,因此在大量資料排序時就會引發該錯誤。

解決方案

建立索引
此範例為對 Log 這個 Collection 的 CreateTime 建立降冪排序的 Index
db.Log.createIndex({"CreateTime":-1})
可以用以下指令來查詢此 Collection 上有多少組 Index
db.Log.getIndexes()
增加索引會導致寫入資料速度變慢,且由於需要額外儲存 Index 資訊,會增加儲存資料所佔的空間,但對排序與搜尋有著正向的效能提升,若該欄位時常使用 where 與 sort 則建議可加上索引提高效能。

增加排序可用的記憶體空間
此範例為增加至 320 MB
db.adminCommand({setParameter:1,internalQueryExecMaxBlockingSortBytes:335544320})
若在不增加索引的狀況下修改預設記憶體大小,會導致排序時佔用更多記憶體空間進而影響到資料庫效能,不是一個治標的做法,建議僅在能確保使用量與不適合加入索引時謹慎使用此方案。

結論

在此案例裡,我採取的解決方案是雙管齊下,目的是確保指令可以正確執行,而增加記憶體上限是評估 MongoDB 主機記憶體總大小尚可負擔,可依照需求彈性決定是否對 Collection 上 Index 而同時確保可正常排序查詢

參考資料

分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.