這篇應該會是難得的從問題反推回去學習的歷程吧,我得好好記錄紀錄。最近我們的 production 發生了 MongoDB 的 sort 操作的限制,具體訊息如下:
MongoDB.Driver.MongoCommandException: Command find failed: Encountered non-retryable error during query :: caused by :: Executor error during find command :: caused by :: Sort operation used more than the maximum 33554432 bytes of RAM.
好吧!問題都發生了,我們先來解決問題,所以我們就先加了 index 上去應急,至於甚麼是 mongoDB 的 index 呢?
什麼是 MongoDB Index 呢?
如果你剛好是 DB 的設計者,你會怎麼找資料返回你的 Client 呢?
這個問題不是很簡單嘛!我就一條一條一條資料過濾,然後再一口氣一起排序,再把你需要的資料返回給你。這個在資料量很小的狀態下,在使用的體驗上是不會有任何感覺的,會覺得資料很快速就拿到了,然而只要資料量一大起來,這樣的查找資料的方式,是不是很低效呢?
在一般正常狀況下,如果你的資料量越大,那麼你的資料量與查詢效率是呈正比的,所以這時候我們就需要 index 來幫助我們解決資料查詢會造成的查詢效率低落的問題,那甚麼是 index 呢?
Index 是用來解決查詢效率低落的問題,同時它也是把雙面刃,在添增 index 的同時,它會有額外的開銷,所以在使用上我們還是要理性的添加 index :
- Pros
- 加速查詢效率。
- 可利用 index 的唯一性來控制資料重複的問題。
- 使用 index 可以在排序時,加速的排序時間與減少記憶體花費。
- Cons
- Index 會讓資料寫入時的速度降低。
- Index 會需要額外的空間儲存。
了解完畢 index 後,我們來看看官方對於 index 怎麼說, MongoDB Manaul Index 。
原來你是使用 Btree 來設計的啊,簡單來說 Btree 時間複雜度是不固定的,與 key 在樹中的哪個位置有關,但最好的情況是 O(1) 。那 MongoDB 有哪些 Index 種類呢?
MongoDB Index 種類
- Unique Index : 唯一 index ,可以確保某個 field 的唯一性。在默認的情況下, MongoDB 在創建 collection 的時候,為 _id 欄位增加的唯一 index 。
- Single Field Index : 單一欄位的 index 。
- Compound Index : 多個欄位的 index 。在日常中,我們比較常會使用這個類型,來建立索引,因為你在查找資料的過程,不太可能只有下一個條件。
- Multikey Index : 有點類似於 single filed index ,不過差別是在 array 的 field 或者是在 array 內的 object 上的 field 建立 index。
- Text Index : 有點類似於 Elasticsearch 上的檢索功能,不過分詞功能沒有想是 Elasticsearch 那麼完善。
- etc
這邊就先總結比較常用的,當然 MongoDB 也是有推出像是 geo 等等方便的 index,細節可以上官方文件觀看, MongoDB Manaul Index 。
OOM Sort Operation
稍微了解一下 index 之後,那麼為什麼會發生 OOM Sort 呢?
我們試著想一下,如果你把所有的資料從 disk 讀取到記憶體中做排序,那麼會發生甚麼是呢?所以 MongoDB 官方會做出這種決定是很正常的。
那我們總得要解決問題吧?我們又該如何解決呢?
增加排序可用的記憶體空間
我們可以增加可用的記憶體空間,這邊的範例是改成 100 MB。
db.adminCommand({ setParameter: 1, internalQueryExecMaxBlockingSortBytes: 104857600 })
使用 Disk 當作記憶體
如果你使用 aggregation pipeline 的話,你可以使用 allowDiskUse: true
來突破記憶體限制,讓 disk 來幫助你!
新增 index
上面兩個方法可以幫你快速解決問題,不過建議還是會使用 index 來解決,記得把 background 設置為 true
,不然你在 production 建立 index 的時候,因為資料量過多造成寫入鎖死。
db.Foo.createIndex({ "Bar": 1 }, { background: true })
總結
至於 index 要怎麼設計規劃呢?讓我賣賣關子,下幾篇會再給大家好好的解釋清楚。
歡迎到我的 Facebook Alan 的筆記本 留言,順手給我個讚吧!你的讚將成為我持續更新的動力,感謝你的閱讀,讓我們一起學習成為更好的自己。