1. 程式人生 > >MongoDB慢查詢效能分析

MongoDB慢查詢效能分析

最近,長期運營後的港臺服出現一個問題,web充值很慢,用gm指令查詢玩家資訊也很慢。最後定位到MongoDB查詢也很慢。   剛開始定位的時候,運營SA直接查指定的玩家,並反映很慢,就猜測是索引的問題。有可能是索引太大,沒法全部放進記憶體,導致讀索引需要多次讀取磁碟,最後整個查詢要4-5s才能完成。後來閱讀了一下MongoDB的文件,發現其也是用B-Tree放索引的,也儘量將索引載入在記憶體裡了。當然,索引有沒有在記憶體裡這個指標,還是沒有日誌或者查詢結果暴露的……   後來,對面運營客服提醒,只有指定角色比較慢,也讓運營的DBA做了分析,發現是有命中唯一索引的。優化只能去查詢部分欄位,避免全量查詢來解決了。但是我讓對方SA匯出了指定查詢慢的玩家資料,這個文件只有不到4MB,ssd讀取這麼小的資料不應該這麼慢   於是繼續翻文件,將explain、loglevel調整增加效能日誌項、mongotop、mongostat等工具都玩了一遍,全部都提示查詢時間在毫秒級別,命中索引,沒看到哪個指標反映到現在秒級查詢時間的狀況   後來猜應該是欄位太多,做了個小工具做分析,列印一個document裡巢狀最深的欄位,以及下級元素最多的欄位。發現由於web充值慢的問題,臺方客服一直往玩家身上發訂單,資料沒有及時清理,所以訂單欄位掛了2000張訂單的資訊……還有一處回收系統的設計缺陷,導致回收資料膨脹,一個數組有上萬大小。這可能導致了MongoDB將資料序列化成bson時產生效能問題,不過所有統計工具都不會分析bson化所需時間,好鬱悶   於是按生效快慢程度排了優先順序,分別針對幾個問題做處理。首先是將查詢介面做特化處理,去掉這次分析出的龐大欄位,該方法生效最快,影響較小,但是由於歷史原因,具體用到的欄位沒有明確列出,沒法做的太細和精準了。然後針對訂單問題,做了玩家上線後清理訂單的操作。最後,回收系統的bug做了修復,上線時做好資料清理   為了進一步壓縮玩家文件大小,還緊急上線了一個orm方面的優化,如果一個結構體裡都是預設欄位,而該結構體也不在一個數組裡,則整個結構體都不做儲存,減少預設欄位對空間的佔用問題。優化後,原來查詢慢的玩家,document大小縮小到原來一半,成效卓著