2021 iThome 鐵人賽 - DAY22 MongoDB Profiler 幾個指令抓拖垮系統的元兇

2021 iThome 鐵人賽 MongoDB披荊斬棘之路


DAY22 MongoDB Profiler 幾個指令抓拖垮系統的元兇

Profiler 查詢推薦指令

1
db.system.profile.find()

一般我們不會這樣做,因為資訊又多又難閱讀,可以加上一些查詢條件。
例如 limit(x) 或者指定某些操作 op 等等。
以下直接推薦我常在使用的指令:

直接找出最慢的

利用執行時間、倒序來找出最慢的幾個。
為了方便閱讀也加入.limit().pretty()語法,後面就不贅述。

1
db.system.profile.find().sort({ millis: -1 }).limit(5).pretty();

利用操作類別查詢

如果你確定慢的 op 是什麼,也可以針對 op 直接排序。

1
db.system.profile.find({"op":"query"}).sort({ millis: -1 });

查詢是否有 COLLSCAN

1
db.system.profile.find({"planSummary": "COLLSCAN"});

利用發生時間來查詢

有設定好最低可接受的執行時間門檻的話,可以用這個方法定期檢查是否有新增慢的查詢。

1
db.system.profile.find().sort({ ts: -1 });

查詢特定時間區

1
2
3
4
5
db.system.profile.find({
"ts": {
$gt: new ISODate("2021-06-13T00:00:00Z"),
$lt: new ISODate("2021-06-13T03:00:00Z")
}}).sort({ millis: -1 });

查詢特定Collection

1
db.system.profile.find({ ns: 'target.collection' });

查找過多文件的查詢

1
db.system.profile.find({ docsExamined: { $gt : 10000 }}).sort({ ts: -1 });

profile size

profile 在系統是有預設 1 Mb 的大小,如果要改變,必須先關閉、刪除現有 profile、重建最後重新開起。因此強烈建議在服務開啟之前就先決定好。

指令如下:

1
2
3
4
5
6
7
8
9
10
11
12

// 1 停用
db.setProfilingLevel(0)

// 2.刪除 (回傳為 true/false)
db.system.profile.drop()

// 3.重建 (回傳為 {"ok": 1})
db.createCollection("system.profile", {capped: true, size: 3000000})

// 4.重開
db.setProfilingLevel(1)

心得

其實在查找效能低落的操作,會用到的指令大概就是這些了,蠻考驗的是對各個參數的熟悉度。
第一階段是了解各個參數,第二階段是定期自動化取得 profile 內容,第三階段是配合自定義的規則來告警,要做到自動化還是需要時間與資源的投入。

問題爆發通常是在線上環境,但你敢在線上環境開profiler嗎?

如果在開發階段就開著 profiler,執行測試後都有回報其結果,就能減少不該存在的操作一路上到正式環境。(舉個最簡單例子,定期察看是否有 Collection scan 就幫助很大了)

有的人反對開 profiler 會慢,但會慢多少?開著 level 1 也有過濾雜訊的功能,我再測試了一下影響並不顯著,況且開發環境從來就不是效能測試的地方,另外就是它是存在 capped collection,實在不用太擔心效能影響劇烈的狀況。

以上我說的是正式營運環境之前建議可以開。

  • 作者: MingYi Chou
  • 版權聲明: 轉載不用問,但請註明出處!本網誌均採用 BY-NC-SA 許可協議。