一次關於mongodb效能踩坑的總結
發現效能問題
上一次匯入資料後,發現系統十分的卡頓,但是才僅僅1000多條資料而已,怎麼會讓系統變得如何的卡頓呢?於是我開始走在排查系統卡頓的原因的道路上。
首先,先定位問題是出現在前端上還是後端上。開啟瀏覽器,輸入localhost:7000
,
然後F12開啟netword。啟動後端專案,檢視log。切換回瀏覽器,右鍵重新整理。結果發現好多些問題:
- 請求傳送的個數比較多。
- 後端每個介面的響應時間都比較長,都超過了1s,這明顯有問題。
- 前端很多請求從: 傳送請求到頁面渲染成功所需要的時間大於了10S(傳送請求時間+後端介面響應時間+下載資源時間,即回傳資料時間+頁面渲染時間)。
從上面這幾個現象可以看出:
- 後端有明顯的問題。
- 前端暫時沒有什麼問題。
好好分析一下,為什麼後端每個介面的響應時間都會超過1s,mongodb是出了名的速度快,一般查詢資料就幾十ms,普通查詢也不會超過300ms。但是看到的介面響應時間卻是超過了1s,有的還是明顯3,4s。
苦苦冥想,細細推測,思來想去,都不知道是怎麼回事,最後只有採用刪程式碼的方式來定位問題了。
當刪除類似於下面的程式碼的時候
Schema.virtual('affixes', {
ref: 'Affix',
localField: '_id',
foreignField: 'businessId',
});
這個時候,發現後端介面的響應時間正常了,可以判斷,這段程式碼起到了一定的作用,但是這只是簡單的連表查詢而已。為什麼就導致介面響應時間多那麼多呢?
我繼續分析,進入到controller.js裡面,將與表關聯查詢的程式碼找出來,終於,我快要發現元凶了,刪除這幾行程式碼,ok,同樣,響應時間正常了。
仔細分析這幾行程式碼,發現了一個很重要的事情: 居然是全表查詢!!而且是3張表關聯的全表查詢!!所以...查詢的資料差不多就是這個量: 2000 * 2000 * 2000, 也怪不得為什麼響應時間會超出1s了。
第一個元凶已經被抓住了。但是我還並不知道為什麼前端從請求到渲染成功的時間怎麼會超過10s,這簡直不能忍。
清空network,然後重新整理,重新發送請求,可以看見傳送了5個左右的請求,而檢視後端的log發現其中3個請求都是在做表關聯的全表查詢,並且reply的時候還是將所有的資料都返回到前端裡去了。
ok,現在我大概已經知道為什麼會有超過10s的響應時間了,下載的資料量也比較大,所以響應時間 = 傳送請求時間 + 後端處理時間 + 下載資源時間 + 渲染時間, 由於資料量比較大,所以導致最後的兩個時間也不小。
現在大概已經都找出了為什麼頁面會卡頓並且遲緩。原因就是沒有做後端分頁,系統裡用的是前端分頁。
效能優化總結
- 查詢資料避免多張表關聯全表查詢。
- 先過濾再關聯查詢,而不是先查詢再關聯表。
- react裡多個列表,一定要設定key。
- 分頁一定不要前端做,因為資料量大了肯定要崩掉的。