

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

# 查詢計畫分析
<a name="performance-query-plan-analysis"></a>

透過解釋計畫進行查詢計畫分析，可提供 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 查詢執行計劃的詳細分析，細分每個元件及其效能特性。

## 整體時間
<a name="overall-timing"></a>

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

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

## 執行階段
<a name="execution-stages"></a>

它描述了 step-by-step程序，顯示資料如何流經不同的操作。 Amazon DocumentDB 

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

### 查詢計畫中的常見階段
<a name="common-stages"></a>

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

#### COLLSCAN （集合掃描）
<a name="collscan-stage"></a>
+ 依文件掃描整個集合文件
+ nReturned：傳回集合中的所有相符文件
+ 可以是昂貴的操作，當沒有索引可用時可見

#### IXSCAN （索引掃描）
<a name="ixscan-stage"></a>
+ 使用索引尋找相符的文件
+ nReturned：僅根據索引比對文件
+ 高效率操作，優於 COLLSCAN

#### SORT
<a name="sort-stage"></a>
+ 根據指定的欄位排序文件
+ 如果查詢中的排序屬性不是索引的一部分，則此階段將明確顯示
+ nReturned：與輸入文件相同的數字
+ 大型結果集的記憶體密集型。若要最佳化，請將排序欄位名稱新增至索引

#### LIMIT\_SKIP
<a name="limit-skip-stage"></a>
+ 控制傳回和略過的文件數量
+ nReturned：受 LIMIT 值限制
+ 用於分頁或 LIMIT 操作

#### 子掃描
<a name="subscan-stage"></a>
+ 執行巢狀查詢操作
+ nReturned：根據子查詢結果而有所不同
+ 用於具有多個階段的複雜查詢

具有高executionTimeMillisEstimate 是最佳化的良好候選項目。

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

## 了解說明計畫執行統計資料中的 docsExamined
<a name="docs-examined"></a>

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

**注意**  
僅適用於 Amazon DocumentDB 8.0.0\+。

### 欄位
<a name="docs-examined-fields"></a>


| 欄位 | 說明 | Level | 
| --- | --- | --- | 
| totalDocsExamined | 在所有執行階段中檢查的文件總數。 | 最上層executionStats | 
| docsExamined | 特定執行階段檢查的文件數量。 | 階段層級 | 

`docsExamined` 欄位會出現在下列階段：


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

**注意**  
`docsExamined` 不會出現在 IXONLYSCAN 階段上，因為查詢完全符合索引，而不需要存取文件。

### 在 Explain Plan executionStats Output 中顯示 docsExamined
<a name="docs-examined-examples"></a>

下列範例使用具有 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)
<a name="docs-examined-collscan"></a>

如果沒有索引，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)
<a name="docs-examined-ixscan"></a>

```
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 個不符合查詢的文件。

#### 含剩餘篩選條件的索引掃描
<a name="docs-examined-ixscan-residual"></a>

```
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 擷取
<a name="docs-examined-fetch-ixscan"></a>

```
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 搭配彙總查詢
<a name="docs-examined-fetch-lookup"></a>

```
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)。