在 MongoDB 中對大型資料集進行排序有時會導致令人沮喪的記憶體不足崩潰。但別擔心——我有一些簡單的提示可以幫助您避免這種情況!在我們深入討論之前,我寫了另一篇關於使用 MongoDB 查詢規劃器來檢查查詢是否有效率的文章。這是了解幕後實際情況並及早發現問題的好方法。
當你對一大塊資料進行排序時,MongoDB 會嘗試將其全部載入記憶體。如果資料集太大,可能會耗盡記憶體並崩潰。以下是如何避免這種情況並確保查詢順利運行的方法。
範例:
db.users.createIndex({ createdAt: 1 });
查詢規劃器輸出:
{ "stage": "FETCH", "inputStage": { "stage": "IXSCAN", "keyPattern": { "createdAt": 1 } } }
在這裡您可以看到 MongoDB 正在使用索引掃描 (IXSCAN),這意味著它非常聰明且有效率!
範例:
db.users.find().sort({ createdAt: 1 });
查詢規劃器輸出:
{ "stage": "FETCH", "inputStage": { "stage": "IXSCAN", "keyPattern": { "createdAt": 1 } } }
不錯! MongoDB 正確使用索引,因此它不會使您的系統陷入困境。
範例:
db.users.find().sort({ createdAt: 1 }).limit(100).skip(0);
查詢規劃器輸出:
{ "stage": "LIMIT", "inputStage": { "stage": "IXSCAN", "keyPattern": { "createdAt": 1 } } }
MongoDB 在這裡很聰明,它限制了結果集,因此它只獲取您現在需要的內容。
範例:
db.users.aggregate([{ $sort: { createdAt: 1 } }], { allowDiskUse: true });
查詢規劃器輸出:
{ "stage": "SORT", "diskUsed": true, "inputStage": { "stage": "COLLSCAN" } }
MongoDB 現在使用磁碟空間來幫助排序。如果您有更強大的計劃,這可能是避免記憶體崩潰的好方法。
這裡有一個保持事情順利運行的提示:如果您在聚合管道中對要嘗試排序的字段執行任何操作(例如轉換它、向其中添加某些內容或調整它) , MongoDB 將刪除索引。一旦刪除索引,MongoDB 就無法使用它來幫助排序,這意味著你的查詢會變慢並使用更多記憶體。
例如,假設您想要依照使用者註冊年份對使用者進行排序。如果你這樣做:
db.users.aggregate([ { $project: { year: { $year: "$createdAt" } } }, { $sort: { year: 1 } } ]);
因為您要將createdAt欄位轉換為年份,所以MongoDB會刪除createdAt上的索引。現在它必須掃描整個集合來對資料進行排序,這會大大減慢速度。
希望這些技巧能讓您的 MongoDB 順利運作!如果您有疑問,請隨時與我們聯繫。快樂編碼! ?
以上是防止 MongoDB 排序中的記憶體不足崩潰:有效的最佳化策略的詳細內容。更多資訊請關注PHP中文網其他相關文章!