View a markdown version of this page

查詢計畫分析 - Amazon DocumentDB

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

查詢計畫分析

透過解釋計畫進行查詢計畫分析,可提供 Amazon DocumentDB 查詢效能的基本洞見。具有 executionStats 的查詢計劃會顯示關鍵指標,包括:

  • 每個階段傳回的文件 (nReturned)

  • 階段特定的執行時間 (executionTimeMillisEstimate)

  • 計畫產生持續時間 (planningTimeMillis)

透過檢查查詢計畫輸出,開發人員可以分析執行模式、評估索引使用率,並識別查詢管道階段的潛在最佳化機會。

若要分析查詢計劃,您可以使用下列格式的 explain() 命令。

db.runCommand({explain: {query document}, verbosity: "executionStats"}) db.collection.find().explain("executionStats");

以下是操作範例:

db.collection.find({ companyname: { '$eq': 'ANYCOMPANY' }, isDeleted: { '$eq': false } }).sort({"createdAt":1}).limit(2).explain("executionStats");

此操作的輸出如下所示:

{ queryPlanner: { plannerVersion: 2, namespace: 'limit_test.test', winningPlan: { stage: 'LIMIT_SKIP', inputStage: { stage: 'SORT', sortPattern: { createdAt: 1 }, inputStage: { stage: 'IXSCAN', indexName: 'companyname_1_createdAt_1_isDeleted_1', direction: 'forward', indexCond: { '$and': [ { companyname: { '$eq': 'ANYCOMPANY' } }, { isDeleted: { '$eq': false } } ] } } } } }, indexFilterSet: false, indexFilterApplied: false, executionStats: { executionSuccess: true, executionTimeMillis: '4.186', planningTimeMillis: '3.909', executionStages: { stage: 'LIMIT_SKIP', nReturned: '2', executionTimeMillisEstimate: '0.199', inputStage: { stage: 'SORT', nReturned: '2', executionTimeMillisEstimate: '0.197', sortPattern: { createdAt: 1 }, inputStage: { stage: 'IXSCAN', nReturned: '34', executionTimeMillisEstimate: '0.151', indexName: 'companyname_1_createdAt_1_isDeleted_1', direction: 'forward', indexCond: { '$and': [ { companyname: { '$eq': 'ANYCOMPANY' } }, { isDeleted: { '$eq': false } } ] } } } } }, serverInfo: { host: 'demo-cluster', port: 27017, version: '5.0.0' }, ok: 1, operationTime: Timestamp({ t: 1759915116, i: 1 }) }

以下是 Amazon DocumentDB 查詢執行計劃的詳細分析,細分每個元件及其效能特性。

整體時間

executionTimeMillis 代表查詢所花費的總時間,包括規劃時間。

planningTimeMillis 代表查詢所花費的總規劃時間。

執行階段

它描述了 Amazon DocumentDB 用來執行查詢step-by-step程序,顯示資料如何流經不同的操作。

"executionStages": { "stage": "[STAGE_NAME]", "nReturned": "[NUMBER_OF_DOCS]", "executionTimeMillisEstimate": "[TIME]", "inputStage": { // Nested stages } }

查詢計畫中的常見階段

以下是查詢計劃中常見的執行階段。每個階段都會傳回 executionTimeMillisEstimate (執行時間) 和 nReturned (文件數量) 指標,以協助評估每個階段的查詢效能。

COLLSCAN (集合掃描)

  • 依文件掃描整個集合文件

  • nReturned:傳回集合中的所有相符文件

  • 可以是昂貴的操作,當沒有索引可用時可見

IXSCAN (索引掃描)

  • 使用索引尋找相符的文件

  • nReturned:僅根據索引比對文件

  • 高效率操作,優於 COLLSCAN

SORT

  • 根據指定的欄位排序文件

  • 如果查詢中的排序屬性不是索引的一部分,則此階段將明確顯示

  • nReturned:與輸入文件相同的數字

  • 大型結果集的記憶體密集型。若要最佳化,請將排序欄位名稱新增至索引

LIMIT_SKIP

  • 控制傳回和略過的文件數量

  • nReturned:受 LIMIT 值限制

  • 用於分頁或 LIMIT 操作

子掃描

  • 執行巢狀查詢操作

  • nReturned:根據子查詢結果而有所不同

  • 用於具有多個階段的複雜查詢

具有高executionTimeMillisEstimate 是最佳化的理想候選者。

注意

executionStats 參數目前不支援更新和刪除命令。

了解說明計畫執行統計資料中的 docsExamined

當您使用 執行查詢時explain("executionStats"),Amazon DocumentDB 會提供檢查指標,協助您了解已掃描多少文件來產生查詢結果。這些指標有助於識別效率不佳的查詢計劃和最佳化效能。

注意

僅適用於 Amazon DocumentDB 8.0.0+。

欄位

欄位 Description Level
totalDocsExamined 在所有執行階段中檢查的文件總數。 頂層 executionStats
docsExamined 特定執行階段檢查的文件數量。 階段層級

docsExamined 欄位會出現在下列階段:

階段 Description
COLLSCAN 集合掃描。會檢查集合中的所有文件。
IXSCAN 索引掃描。只會檢查符合索引條件的文件。
FETCH 當最佳化工具從 IXSCAN 擷取不同階段的文件時,FETCH 階段會報告 docsExamined。在索引掃描計劃中,子 IXSCAN 階段不會報告 docsExamined。在 $lookup 計劃中,FETCH 階段及其子階段都可以報告 docsExamined。
注意

docsExamined 不會出現在 IXONLYSCAN 階段上,因為查詢完全從索引滿足而不存取文件。

在 Explain Plan executionStats Output 中顯示 docsExamined

下列範例使用具有 500,000 個文件的集合,並示範在不同查詢執行階段之間如何docsExamined變更。

建立範例資料:

for (let i = 0; i < 500000; i++) { db.coll.insertOne({ number: i, arr: [i, [i+1]], value: "test", bool: i % 2 === 0 }); }

集合掃描 (COLLSCAN)

如果沒有索引,Amazon DocumentDB 會執行完整的集合掃描。

db.coll.find({ "number": { "$lt": 500 } }).explain("executionStats").executionStats

輸出:

{ "executionSuccess" : true, "nReturned" : "500", "executionTimeMillis" : "282.055", "planningTimeMillis" : "0.085", "totalDocsExamined" : "500000", "executionStages" : { "stage" : "COLLSCAN", "nReturned" : "500", "executionTimeMillisEstimate" : "281.915", "docsExamined" : "500000", "filter" : { "number" : { "$lt" : 500 } } } }

已檢查所有 500,000 個文件,以傳回 500 個結果。在數字欄位上建立索引可改善此狀況。

索引掃描 (IXSCAN)

db.coll.createIndex({ number: 1 }); db.coll.find({ "number": { "$lt": 5000 } }).explain("executionStats").executionStats

輸出:

{ "executionSuccess" : true, "nReturned" : "5000", "executionTimeMillis" : "3.047", "planningTimeMillis" : "0.296", "totalDocsExamined" : "5000", "executionStages" : { "stage" : "IXSCAN", "nReturned" : "5000", "executionTimeMillisEstimate" : "2.576", "indexName" : "number_1", "direction" : "forward", "docsExamined" : "5000", "indexCond" : { "$and" : [ { "number" : { "$lt" : 5000 } } ] } } }

使用 索引時,只會檢查和擷取 500,000 個文件中的 5,000 個,符合傳回的數目。索引條件篩選掉 495,000 個不符合查詢的文件。

含剩餘篩選條件的索引掃描

db.coll.find({ "number": { "$lt": 5000 }, "arr": { "$gt": 4000 } }).explain("executionStats").executionStats

輸出:

{ "executionSuccess" : true, "nReturned" : "999", "executionTimeMillis" : "15.367", "planningTimeMillis" : "0.115", "totalDocsExamined" : "5000", "executionStages" : { "stage" : "IXSCAN", "nReturned" : "999", "executionTimeMillisEstimate" : "15.170", "indexName" : "number_1", "direction" : "forward", "docsExamined" : "5000", "indexCond" : { "$and" : [ { "number" : { "$lt" : 5000 } } ] }, "filter" : { "arr" : { "$gt" : 4000 } } } }

索引條件符合 500,000 個文件中的 5,000 個文件,然後 上的剩餘篩選條件將結果arr減少為 999。docsExamined 值 5,000 反映在索引條件之後,但在套用剩餘篩選條件之前檢查的所有文件。

使用 IXSCAN 擷取

db.coll.find({ "$or": [{ "number": { "$lt": 100000 } }, { "number": { "$gt": 400000 } }] }).explain("executionStats").executionStats

輸出:

{ "executionSuccess" : true, "nReturned" : "199999", "executionTimeMillis" : "899.801", "planningTimeMillis" : "0.183", "totalDocsExamined" : "199999", "executionStages" : { "stage" : "FETCH", "nReturned" : "199999", "executionTimeMillisEstimate" : "894.141", "docsExamined" : "199999", "inputStage" : { "stage" : "IXOR", "nReturned" : "0", "executionTimeMillisEstimate" : "874.897", "inputStages" : [ { "stage" : "IXSCAN", "nReturned" : "100000", "executionTimeMillisEstimate" : "462.208", "indexName" : "number_1", "indexCond" : { "$and" : [ { "number" : { "$lt" : 100000 } } ] } }, { "stage" : "IXSCAN", "nReturned" : "99999", "executionTimeMillisEstimate" : "412.684", "indexName" : "number_1", "indexCond" : { "$and" : [ { "number" : { "$gt" : 400000 } } ] } } ] } } }

當 Amazon DocumentDB 最佳化工具使用擷取階段擷取文件時,FETCH 階段會報告 docsExamined。子 IXSCAN 階段不會報告,docsExamined因為它們只會掃描索引鍵而不直接存取文件。

FETCH 搭配彙總查詢

db.coll.explain("executionStats").aggregate([ { $match: { "number": { "$lt": 5 } } }, { $lookup: { from: "coll", pipeline: [{ $match: { "number": { "$lt": 3 } } }], as: "sub" } } ]).executionStats

輸出:

{ "executionSuccess" : true, "nReturned" : "5", "executionTimeMillis" : "0.525", "planningTimeMillis" : "0.327", "totalDocsExamined" : "9", "executionStages" : { "stage" : "NESTED_LOOP_LOOKUP", "nReturned" : "5", "executionTimeMillisEstimate" : "0.163", "inputStages" : [ { "stage" : "IXSCAN", "nReturned" : "5", "executionTimeMillisEstimate" : "0.039", "indexName" : "number_1", "direction" : "forward", "docsExamined" : "5", "indexCond" : { "$and" : [ { "number" : { "$lt" : 5 } } ] } }, { "stage" : "FETCH", "nReturned" : "1", "executionTimeMillisEstimate" : "0.009", "docsExamined" : "1", "inputStage" : { "stage" : "AGGREGATE", "nReturned" : "1", "executionTimeMillisEstimate" : "0.044", "inputStage" : { "stage" : "IXSCAN", "nReturned" : "3", "executionTimeMillisEstimate" : "0.013", "indexName" : "number_1", "direction" : "forward", "docsExamined" : "3", "indexCond" : { "$and" : [ { "number" : { "$lt" : 3 } } ] } } } } ] } }

外部 IXSCAN 檢查了 5 個符合編號 < 5 的文件。內部 IXSCAN 檢查了 3 個符合編號 < 3 的文件,FETCH 階段檢查了 1 個彙總結果。9 totalDocsExamined的 是所有階段的總和 (5 + 3 + 1)。