

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 查询计划分析
<a name="performance-query-plan-analysis"></a>

通过解释计划进行查询计划分析可提供对 Amazon DocumentDB 查询性能的基本见解。使用 ExecutionStats 的查询计划揭示了关键指标，包括：
+ 每个阶段返回的文档（n已返回）
+ Stage-specific 执行时间（执行TimeMillisEstimate）
+ 计划生成持续时间（计划TimeMillis）

通过检查查询计划输出，开发人员可以分析执行模式，评估索引利用率，并识别整个查询管道阶段的潜在优化机会。

要分析查询计划，您可以使用以下格式的 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>

执行TimeMillis 表示查询所花费的总时间，包括计划时间。

planning TimeMillis 表示查询所花费的总计划时间。

## 执行阶段
<a name="execution-stages"></a>

它描述了 Amazon DocumentDB 用于执行查询的分步过程，显示了数据如何通过不同的操作流动。

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

### 查询计划中的常见阶段
<a name="common-stages"></a>

以下是查询计划中常见的执行阶段。每个阶段都返回执行TimeMillisEstimate （执行时间）和 nReturn（文档数）指标，以帮助评估每个阶段的查询性能。

#### COLLSCAN（馆藏扫描）
<a name="collscan-stage"></a>
+ 逐个文档扫描整个馆藏文档
+ nReturen：返回集合中所有匹配的文档
+ 可能是一项昂贵的操作，在没有可用的索引时可以看到

#### IXSCAN（索引扫描）
<a name="ixscan-stage"></a>
+ 使用索引查找匹配的文档
+ nReturen：仅根据索引匹配文档
+ 高效运行，比 COLLSCAN 更受青睐

#### SORT
<a name="sort-stage"></a>
+ 根据指定字段对文档进行排序
+ 如果查询中的排序属性不是索引的一部分，则此阶段将显式显示
+ n返回：与输入文档的编号相同
+ Memory-intensive 用于大型结果集。要进行优化，请将排序字段名称添加到索引中

#### 极限\_跳过
<a name="limit-skip-stage"></a>
+ 控制返回和跳过的文档数量
+ n返回：受限值限制
+ 用于分页或限制操作

#### 子扫描
<a name="subscan-stage"></a>
+ 执行嵌套查询操作
+ nReturen：因子查询结果而异
+ 用于具有多个阶段的复杂查询

执行力高的阶段TimeMillisEstimate 是优化的理想选择。

**注意**  
ExecutionStats 参数目前不支持更新和删除命令。

## 在 “解释计划执行统计信息” 中了解已检查的文档
<a name="docs-examined"></a>

当您使用运行查询时`explain("executionStats")`，Amazon DocumentDB 会提供检查指标，帮助您了解为生成查询结果而扫描了多少文档。这些指标对于识别低效的查询计划和优化性能非常有用。

**注意**  
仅在亚马逊 DocumentDB 8.0.0\+ 版本中可用。

### 字段
<a name="docs-examined-fields"></a>


| 字段 | 说明 | 级别 | 
| --- | --- | --- | 
| 总计 DocsExamined | 在所有执行阶段检查的文档总数。 | Top-level 执行统计 | 
| 已检查文档 | 特定执行阶段检查的文件数量。 | Stage-level | 

该`docsExamined`字段出现在以下阶段：


| 暂存区 | 说明 | 
| --- | --- | 
| COLLSCAN | 馆藏扫描。馆藏中的所有文件都经过检查。 | 
| IXSCAN | 索引扫描。仅检查符合索引条件的文档。 | 
| FETCH | 当优化器在与 IXSCAN 不同的阶段检索文档时，FETCH 阶段会报告 docSexamined。在索引扫描计划中，子级 IXSCAN 阶段不报告 docSexamined。在 $lookup 计划中，FETCH 阶段及其子阶段都可能报告 docSexamined。 | 

**注意**  
`docsExamined`不会出现在 IXONLYSCAN 阶段上，因为无需访问文档即可完全从索引中满足查询。

### 在 “解释计划” 执行统计输出中显示已检查的文档
<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
                    }
                }
            ]
        }
    }
}
```

使用该索引，在50万份文档中仅检查和提取了5,000份，与返回的数字相符。索引条件筛选出了 49.5万份与查询不匹配的文档。

#### 使用残留过滤器进行索引扫描
<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 个。5,000 的`docsExamined`值反映了在索引条件之后但在应用残差过滤器之前检查的所有文档。

#### 使用 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`因为它们只扫描索引键，而不直接访问文档。

#### 使用聚合查询获取
<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）。