db.system.profile.find()
一般我們不會這樣做,因為資訊又多又難閱讀,可以加上一些查詢條件。
例如 limit(x)
或者指定某些操作 op
等等。
以下直接推薦我常在使用的指令:
利用執行時間、倒序來找出最慢的幾個。
為了方便閱讀也加入.limit()
、.pretty()
語法,後面就不贅述。
db.system.profile.find().sort({ millis: -1 }).limit(5).pretty();
如果你確定慢的 op 是什麼,也可以針對 op 直接排序。
db.system.profile.find({"op":"query"}).sort({ millis: -1 });
db.system.profile.find({"planSummary": "COLLSCAN"});
有設定好最低可接受的執行時間門檻的話,可以用這個方法定期檢查是否有新增慢的查詢。
db.system.profile.find().sort({ ts: -1 });
db.system.profile.find({
"ts": {
$gt: new ISODate("2021-06-13T00:00:00Z"),
$lt: new ISODate("2021-06-13T03:00:00Z")
}}).sort({ millis: -1 });
db.system.profile.find({ ns: 'target.collection' });
db.system.profile.find({ docsExamined: { $gt : 10000 }}).sort({ ts: -1 });
profile 在系統是有預設 1 Mb 的大小,如果要改變,必須先關閉、刪除現有 profile、重建最後重新開起。因此強烈建議在服務開啟之前就先決定好。
指令如下:
// 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
,實在不用太擔心效能影響劇烈的狀況。
以上我說的是正式營運環境之前,建議可以開。
本系列文章會同步發表於我個人的部落格 Pie Note