1. 程式人生 > 實用技巧 >MongoDB 查詢時排序超過記憶體限制的問題

MongoDB 查詢時排序超過記憶體限制的問題

org.springframework.data.mongodb.UncategorizedMongoDbException: Query failed with error code 17144 and error message 'Executor error: Overflow sort stage buffered data usage of 33554898 bytes exceeds internal limit of 33554432 bytes' on server 127.0.0.1:27017; nested exception is com.mongodb.MongoQueryException: Query failed with error code 17144 and error message 'Executor error: Overflow sort stage buffered data usage of 33554898 bytes exceeds internal limit of 33554432 bytes' on server 127.0.0.1:27017
    at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:
107) at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:2114) at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:1957) at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:
1763) at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1746) at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:624) at com.controller.TestController.getList(TestController.java:1216) at com..controller.TestController$$FastClassBySpringCGLIB$$d9a15731.invoke(
<generated>)

報錯原因:在排序欄位未利用到索引的情況下,若超過32M記憶體則會被Abort,語句直接返回報錯

Sort operation used more than the maximum 33554432 bytes of RAM.,33554432 bytes算下來正好是32Mb,而mongodb的sort操作是把資料拿到記憶體中再進行排序的,為了節約記憶體,預設給sort操作限制了最大記憶體為32Mb,當資料量越來越大直到超過32Mb的時候就丟擲異常了!

解決方式:給具體要對哪個欄位加索引,可根據需求自己定義,其中1表示升序排列,-1表示降序排列。

MongoDB排序方式:MongoDB可以使用索引掃描來進行排序,那麼結果將不包括SORT stage。否則如果MongoDB無法使用索引進行排序,那麼查詢計劃將包括SORT stage。

使用索引掃描的效率是遠大於直接將結果集放在記憶體排序的,所以MongoDB為了使查詢語句更有效率的執行,限制了 排序記憶體的使用,因而規定了只能使用 32M。

注意保持查詢中組合排序的升降序和組合索引中的 方向 保持 全部相同 或 全部相反

索引操作語句

db.getCollection('document').getIndexes() 檢視當前索引

db.getCollection('document').createIndex({"age": 1}) 建立單個索引

db.getCollection('document').createIndex({"age": 1,"name":1},{"name":"user"}) 一個索引名稱下包含多個key

db.getCollection('document').dropIndex("age") 刪除索引