返回文章列表

MongoDB效能調校工具詳解

本文探討 MongoDB 效能調校的關鍵工具與技巧,涵蓋 explain() 方法解析查詢計畫、Profiler 監控伺服器負載、ServerStatus() 和 CurrentOp() 檢視伺服器狀態,以及 MongoDB Compass 圖形化管理。此外,文章也詳細說明如何解讀 explain()

資料函式庫 效能調校

MongoDB 提供多種免費工具,對於資料函式庫效能調校至關重要。explain() 方法能分析查詢計畫,顯示 MongoDB 如何執行查詢,包括索引和排序方法,藉此找出效能瓶頸。Profiler 則能捕捉和分析伺服器的負載狀況,找出效能瓶頸。ServerStatus() 和 CurrentOp() 命令提供伺服器狀態資訊,前者顯示整體狀態,後者顯示目前執行中的操作。MongoDB Compass 提供圖形化介面,方便管理和監控資料函式庫,可視覺化資料、執行查詢和管理索引。此外,善用 explain() 輸出結果,搭配索引建立與查詢分析器,能有效提升查詢效能。MongoDB 日誌則記錄慢查詢等資訊,可透過調整慢操作閾值或設定日誌級別控制輸出內容,並搭配 mtools 工具包進行分析與視覺化。

MongoDB效能調校工具

在進行 MongoDB 效能調校時,熟悉 MongoDB 提供的免費工具是非常重要的。這些工具包括:

explain() 方法

explain() 方法允許您檢查查詢計劃,瞭解 MongoDB 如何執行查詢操作。它是調校 MongoDB 效能的必備工具。

db.customers.find(
    {
        FirstName: "RUTH",
        LastName: "MARTINEZ",
        Phone: 496523103
    },
    { Address: 1, dob: 1 }
).sort({ dob: 1 }).explain();

內容解密:

  • 使用 explain() 方法來分析查詢計劃。
  • explain() 方法顯示了 MongoDB 如何執行查詢,包括使用的索引和排序方法。
  • 透過分析查詢計劃,可以最佳化查詢效能。

分析器(Profiler)

分析器允許您捕捉和分析 MongoDB 伺服器的負載情況。透過分析器,可以找出效能瓶頸並進行最佳化。

ServerStatus() 和 CurrentOp()

ServerStatus() 和 CurrentOp() 命令提供了有關 MongoDB 伺服器狀態的資訊。ServerStatus() 顯示了伺服器的整體狀態,而 CurrentOp() 則顯示了目前正在執行的操作。

MongoDB Compass

MongoDB Compass 是 MongoDB 提供的圖形化工具,提供了一個使用者友好的介面來管理和監控 MongoDB 資料函式庫。它可以用於視覺化資料、執行查詢和管理索引等。

MongoDB 效能調校:深入理解 explain()

在 MongoDB 效能調校過程中,explain() 方法是不可或缺的工具。它能夠提供查詢執行計畫的詳細資訊,幫助開發者瞭解查詢的最佳化方式以及 MongoDB 如何選擇執行計畫。

使用 explain() 方法

要使用 explain() 方法,我們需要在集合物件上呼叫它,並傳遞一個 find()update()insert()aggregate() 操作。例如:

var explainCsr = db.customers.explain().find(
  {
    FirstName: "RUTH",
    LastName: "MARTINEZ",
    Phone: 496523103
  },
  { Address: 1, dob: 1 }
).sort({ dob: 1 });

var explainDoc = explainCsr.next();

程式碼解密:

  1. db.customers.explain():在 customers 集合上呼叫 explain() 方法,傳回一個可解釋的查詢遊標。
  2. .find():定義查詢條件,尋找符合 FirstNameLastNamePhone 的檔案。
  3. .sort({ dob: 1 }):根據 dob 欄位進行升序排序。
  4. explainCsr.next():取得查詢執行計畫的檔案。

解析 explain() 輸出

explain() 方法傳回的 JSON 檔案包含了查詢執行計畫的詳細資訊。其中最重要的是 winningPlan 部分,它描述了 MongoDB 選擇的執行計畫。

{
  "stage": "PROJECTION_SIMPLE",
  "transformBy": {
    "Address": 1,
    "dob": 1
  },
  "inputStage": {
    "stage": "SORT",
    "sortPattern": {
      "dob": 1
    },
    // ...
  }
}

內容解密:

  1. "stage": "PROJECTION_SIMPLE":表示簡單投影階段,將結果限制在指定的欄位。
  2. "transformBy":定義投影的欄位,僅傳回 Addressdob
  3. "inputStage":表示前一階段的輸出作為當前階段的輸入。

簡化 explain() 輸出

為了更方便地理解執行計畫,可以使用 mongoTuning.quickExplain 函式來列印簡化的執行步驟:

Mongo Shell> mongoTuning.quickExplain(explainDoc)
1 IXSCAN Phone_1
2 FETCH
3 SORT_KEY_GENERATOR
4 SORT
5 PROJECTION_SIMPLE

內容解密:

  1. IXSCAN Phone_1:使用 Phone_1 索引進行索引掃描。
  2. FETCH:根據索引結果讀取檔案內容,並過濾不符合條件的檔案。
  3. SORT_KEY_GENERATOR:為排序操作準備資料。
  4. SORT:根據 dob 欄位進行排序。
  5. PROJECTION_SIMPLE:進行簡單投影,傳回指定的欄位。

其他執行計畫

explain() 方法還可以提供被拒絕的執行計畫,儲存在 rejectedPlans 陣列中。這些計畫可能由於估計的工作量較大而被拒絕。

執行統計資訊

透過傳遞 'executionStats' 引數給 explain() 方法,可以取得查詢執行的統計資訊,包括每個階段的效能資料。

var explainObj = db.customers.explain('executionStats').find(
  { FirstName: "RUTH", LastName: "MARTINEZ", Phone: 496523103 },
  { Address: 1, dob: 1 }
).sort({ dob: 1 });

var explainDoc = explainObj.next();

程式碼解密:

  1. 'executionStats':啟用執行統計資訊的收集。
  2. .find().sort():定義查詢和排序條件。

MongoDB 查詢最佳化:explain() 與查詢分析工具

使用 explain() 分析查詢效能

在 MongoDB 中,explain() 是一個強大的工具,用於分析查詢的執行計劃和效能。透過 explain(),開發者可以深入瞭解查詢的執行過程,找出效能瓶頸,並進行最佳化。

explain() 的基本用法

explain() 可以用於分析查詢的執行計劃,例如:

db.customers.explain('executionStats').find(
  { Country: 'United Kingdom', 'views.title': 'CONQUERER NUTS' },
  { City: 1, LastName: 1, phone: 1 }
).sort({ City: 1, LastName: 1 });

上述查詢將傳回查詢的執行計劃和統計資訊,包括執行時間、掃描的檔案數等。

executionStats 的解讀

executionStats 提供了查詢執行的詳細統計資訊,包括:

  • executionTimeMillisEstimate:估計的執行時間(毫秒)
  • keysExamined:掃描的索引鍵數量
  • docsExamined:掃描的檔案數量

mongoTuning.executionStats() 的使用

mongoTuning.executionStats() 是一個自定義函式,用於簡化 explain() 輸出的解讀。例如:

mongoTuning.executionStats(explainDoc);

輸出結果如下:

1 COLLSCAN ( ms:12 docs:411121)
2 SORT_KEY_GENERATOR ( ms:12)
3 SORT ( ms:12)
4 PROJECTION_SIMPLE ( ms:12)
Totals: ms: 253 keys: 0 Docs: 411121

從輸出結果中,我們可以看到查詢的執行計劃和統計資訊,包括 COLLSCAN(全表掃描)和 SORT(排序)操作。

建立索引最佳化查詢

根據 explain() 的輸出結果,我們可以建立索引來最佳化查詢。例如:

db.customers.createIndex(
  { Country: 1, 'views.title': 1, City: 1, LastName: 1 },
  { name: 'ExplainExample' }
);

建立索引後,再次執行查詢,輸出結果如下:

1 IXSCAN ( ExplainExample ms:0 keys:685)
2 FETCH ( ms:0 docs:685)
3 PROJECTION_SIMPLE ( ms:0)
Totals: ms: 2 keys: 685 Docs: 685

從輸出結果中,我們可以看到查詢的執行時間大幅減少,掃描的檔案數量也大大減少。

視覺化 explain() 輸出

除了使用 explain() 命令列工具外,還有許多視覺化工具可用於呈現 explain() 輸出結果,例如 MongoDB Compass 和 dbKoda。這些工具可以幫助開發者更直觀地瞭解查詢的執行計劃和效能。

MongoDB Compass 的視覺化輸出

MongoDB Compass 提供了一個圖形化的介面,用於呈現 explain() 輸出結果。例如:

此圖示顯示了查詢的執行計劃和統計資訊,包括索引掃描和檔案擷取操作。

dbKoda 的視覺化輸出

dbKoda 是另一個支援視覺化 explain() 輸出的工具。例如:

此圖示顯示了查詢的執行計劃和統計資訊,包括索引掃描和排序操作。

查詢分析器(Query Profiler)

除了 explain() 外,MongoDB 還提供了查詢分析器(Query Profiler),用於收集資料函式庫上執行的命令資訊。查詢分析器可以幫助開發者找出需要最佳化的查詢,並進行相應的最佳化。

查詢分析器可以設定為三個級別,分別用於收集不同程度的資訊。開發者可以根據需要選擇適當的級別,以收集所需的資訊。

MongoDB 效能調校:深入剖析 Profiling 機制

Profiling 層級設定與控制

MongoDB 提供了一個強大的 profiling 工具,用於收集資料函式庫操作的詳細資訊。Profiling 的層級可以透過 db.setProfilingLevel() 命令進行設定,主要分為三個層級:

  • 0:預設層級,關閉 profiling 功能。
  • 1:只收集執行時間超過 slowms 閾值的操作資訊。
  • 2:收集所有操作的資訊,無論執行時間是否超過 slowms 閾值。

db.setProfilingLevel() 命令的語法如下:

db.setProfilingLevel(level, { slowms: slowMsThreshold, sampleRate: samplingRate });

其中,level 對應上述三個層級,slowMsThreshold 設定 layer 1 tracing 的毫秒執行閾值,而 samplingRate 決定了隨機取樣的比例。

程式碼範例:設定 Profiling 層級

db.setProfilingLevel(1, { slowms: 2, sampleRate: 1 });

內容解密:

此範例程式碼將 profiling 層級設定為 1,並將 slowms 閾值設定為 2 毫秒,sampleRate 設定為 1(即收集所有符合條件的操作)。這意味著 MongoDB 將記錄所有執行時間超過 2 毫秒的操作。

Profiling 資訊儲存與分析

Profiling 資訊儲存在 system.profile 集合中,該集合是一個固定大小的 capped collection。當集合大小達到上限時,舊的紀錄將被新的紀錄取代。預設大小為 1MB,可以根據需要調整。

調整 system.profile 集合大小

db.setProfilingLevel(0);
db.system.profile.drop();
db.createCollection("system.profile", { capped: true, size: 10485760 }); // 10MB
db.setProfilingLevel(1);

內容解密:

這段程式碼首先關閉 profiling,然後刪除 system.profile 集合。接著,重新建立一個大小為 10MB 的 system.profile 集合,並將 profiling 層級設定回 1。這樣可以增加儲存更多 profiling 資訊的能力。

分析 Profiling 資料

分析 system.profile 中的資料,可以使用 MongoDB 的 find()aggregate() 方法。由於單一操作的執行統計資料可能會分散在多個集合紀錄中,因此需要對資料進行聚合分析。

聚合分析程式碼範例

db.system.profile.aggregate([
    {
        $group: {
            _id: { cursorid: "$cursorid" },
            count: { $sum: 1 },
            "queryHash-max": { $max: "$queryHash" },
            "millis-sum": { $sum: "$millis" },
            "ns-max": { $max: "$ns" }
        }
    },
    {
        $group: {
            _id: { queryHash: "$queryHash-max", collection: "$ns-max" },
            count: { $sum: 1 },
            millis: { $sum: "$millis-sum" }
        }
    },
    { $sort: { millis: -1 } },
    { $limit: 10 }
]);

內容解密:

此聚合管道首先根據 cursorid 對 profiling 資料進行分組,計算每個分組的操作次數、最大 queryHash、總執行時間和最大名稱空間。然後,再根據 queryHash 和名稱空間進行第二次分組,累計操作次數和總執行時間。最後,按照總執行時間降序排序,並限制輸出結果為前 10 名。

MongoDB效能調校:查詢分析與日誌管理

使用查詢分析器最佳化MongoDB命令

在進行MongoDB效能調校時,瞭解哪些查詢需要最佳化是非常重要的。MongoDB提供了查詢分析器(query profiler)來幫助我們找出需要調校的命令。查詢分析器可以記錄查詢的執行時間、檢查的檔案數量以及執行計劃摘要等資訊。

以下是一個範例,展示瞭如何使用查詢分析器取得特定查詢的資訊:

{
  "op": "command",
  "ns": "MongoDBTuningBook.$cmd",
  "command": {
    "find": "collectionName",
    "filter": { /* 篩選條件 */ },
    "sort": { "phone": 1 },
    "projection": { /* 投影欄位 */ },
    "$db": "MongoDBTuningBook"
  },
  "docsExamined": 101,
  "millis": 31,
  "planSummary": "IXSCAN { Country: 1, views.title: 1, City: 1, LastName: 1, phone: 1 }"
}

內容解密:

  • op: 操作型別,表示這是一個命令操作。
  • ns: 名稱空間,包含資料函式庫名稱和集合名稱。
  • command: 執行的命令內容,包括查詢條件、排序欄位和投影欄位等。
  • docsExamined: 檢查的檔案數量,表示查詢過程中掃描了多少檔案。
  • millis: 執行時間,單位為毫秒,表示查詢的執行耗時。
  • planSummary: 執行計劃摘要,顯示了查詢使用的索引掃描(IXSCAN)。

查詢分析器提供了一個基礎的最佳化起點。進一步的最佳化可以透過生成完整的執行計劃(包括executionStats)來實作,並判斷是否可以獲得更好的執行計劃。

利用MongoDB日誌進行調校

除了查詢分析器,MongoDB的日誌也是取得查詢資訊的重要來源。預設情況下,只有超過慢操作閾值(slowms)的命令才會被記錄到日誌中。我們可以透過調整慢操作閾值或設定日誌級別來控制日誌輸出的內容。

設定日誌級別

使用db.setLogLevel命令可以設定特定操作的記錄級別。例如,要記錄所有find()操作,可以執行以下命令:

db.setLogLevel(2, 'query');

執行完需要調校的查詢後,記得將日誌級別還原到預設值,以避免過多的日誌輸出:

db.setLogLevel(0, 'query');

分析日誌內容

假設我們執行了一個查詢並在日誌中記錄了相關資訊,以下是日誌內容的一個範例:

2020-06-03T07:14:56.871+0000 I COMMAND [conn597] command sample_airbnb.listingsAndReviews appName: "MongoDB Shell" command: find { find: "listingsAndReviews", filter: { name: "Ribeira Charming Duplex" }, lsid: { id: UUID("01885ece-c731-4549-8b4f-864fe527888c") }, $db: "sample_airbnb" } planSummary: IXSCAN { name: 1 } keysExamined:1 docsExamined:1 cursorExhausted:1 numYields:0 nreturned:1 queryHash:01AEE5EC planCacheKey:4C5AEA2C reslen:29543 locks:{ ReplicationStateTransition: { acquireCount: { w: 1 } }, Global: { acquireCount: { r: 1 } }, Database: { acquireCount: { r: 1 } }, Collection: { acquireCount: { r: 1 } }, Mutex: { acquireCount: { r: 1 } } } storage:{} protocol:op_msg 0ms

內容解密:

  • 時間戳記(2020-06-03T07:14:56.871+0000):表示日誌記錄的時間。
  • 命令類別(COMMAND):表示這是一條命令相關的日誌。
  • 名稱空間(sample_airbnb.listingsAndReviews):表示操作的資料函式庫和集合。
  • 命令型別(find):表示執行的操作型別。
  • 篩選條件(filter: { name: “Ribeira Charming Duplex” }):顯示了查詢的篩選條件。
  • 執行計劃摘要(planSummary: IXSCAN { name: 1 }):表示使用了索引掃描。
  • 統計資訊(keysExamined:1 docsExamined:1 nreturned:1):提供了查詢的詳細統計資訊。

日誌管理工具

雖然直接閱讀日誌可以獲得所需資訊,但日誌的格式可能較為複雜。mtools工具包提供了諸如mlogfiltermplotqueries等工具,可以幫助過濾和視覺化日誌資料,使得分析更加便捷。