

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

# 對效能和資源使用率進行故障診斷
<a name="user_diagnostics"></a>

本節提供 Amazon DocumentDB 部署中常見診斷問題的問題和解決方案。這些範例會提供使用 *mongo 殼層*，而且範圍限定在個別執行個體的示範。若要尋找執行個體端點 , 請參閱[了解 Amazon DocumentDB 端點](endpoints.md)。

**Topics**
+ [如何判斷透過 Mongo API 在集合上執行的插入、更新和刪除操作數目？](#user-diag-performed-operations)
+ [如何分析快取效能？](#user-diag-cache-perf)
+ [如何尋找並終止長時間執行或封鎖的查詢？](#user_diagnostics-query_terminating)
+ [如何查看查詢計畫並最佳化查詢？](#user_diagnostics-query_plan)
+ [如何查看彈性叢集中的查詢計劃？](#user-diagnostics-ec-query-plan)
+ [如何列出執行個體上所有正在執行的操作？](#user_diagnostics-list_queries)
+ [如何知道查詢何時進行？](#user_diagnostics-query_progressing)
+ [如何判斷系統突然緩慢執行的原因？](#user_diagnostics-speed_change)
+ [如何判斷一或多個叢集執行個體上高 CPU 使用率的原因？](#user_diagnostics-cpu_utilization)
+ [如何判斷執行個體上的開啟游標？](#user_diagnostics-open_cursors)
+ [如何判斷目前的 Amazon DocumentDB 引擎版本？](#user_diagnostics-engine_version)
+ [如何分析索引用量並識別未使用的索引？](#user-diag-index-usage)
+ [如何識別缺少的索引？](#user_diagnostics-identify_missing_indexes)
+ [如何判斷資料庫集合膨脹？](#performance-collection-bloat)
+ [有用的查詢摘要](#user_diagnostics-useful_queries)

## 如何判斷透過 Mongo API 在集合上執行的插入、更新和刪除操作數目？
<a name="user-diag-performed-operations"></a>

若要檢視在特定集合上執行的插入、更新和刪除操作數目，請在該集合上執行下列命令：

```
db.collection.stats()
```

此命令的輸出在其 `opCounters` 欄位下描述下列項目：
+ **numDocsIns** - 插入此集合的文件數量。這包括使用 `insert`和 `insertMany`命令插入的文件，以及 upsert 插入的文件。
+ **numDocsUpd** - 此集合中的文件更新數量。這包括使用 `update`和 `findAndModify`命令更新的文件。
+ **numDocsDel** - 從此集合中刪除的文件數量。這包括使用 `deleteOne`、`remove`、 `deleteMany`和 `findAndModify`命令刪除的文件。
+ **lastReset** - 這些計數器上次重設的時間。此命令提供的統計資料會在啟動/停止叢集或向上/向下擴展執行個體時重設。

執行中 的範例輸出`db.collection.stats()`如下所示。

```
{
    "ns" : "db.test",
    "count" : ...,
    "size" : ...,
    "avgObjSize" : ...,
    "storageSize" : ...,
    "capped" : false,
    "nindexes" : ...,
    "totalIndexSize" : ...,
    "indexSizes" : {
        "_id_" : ...,
        "x_1" : ...
    },
    "collScans" : ...,
    "idxScans" : ...,
    "opCounter" : {
        "numDocsIns" : ...,
        "numDocsUpd" : ...,
        "numDocsDel" : ...
    },
    "cacheStats" : {
        "collBlksHit" : ...,
        "collBlksRead" : ..,
        "collHitRatio" : ...,
        "idxBlksHit" : ...,
        "idxBlksRead" : ...,
        "idxHitRatio" : ...
    },
    "lastReset" : "2022-09-02 19:41:40.471473+00",
    "ok" : 1,
    "operationTime" : Timestamp(1662159707, 1)
}
```

透過 Mongo API 檢視插入、更新和刪除操作的集合特定計數器時，應使用此 stats 命令。檢視集合特定操作計數器的另一種方法是啟用 DML 稽核。您可以在 中檢視一分鐘時間間隔內所有集合的插入、更新和刪除操作數目[使用 CloudWatch 監控 Amazon DocumentDB](cloud_watch.md)。

## 如何分析快取效能？
<a name="user-diag-cache-perf"></a>

分析快取效能可以深入了解資料擷取和系統效能的效率，並根據從磁碟讀取的資料量與快取的資料量而定。我們提供有關快取命中次數 （從快取讀取的資料） 和快取未命中次數 （在快取中找不到並從磁碟讀取的資料） 的快取統計資料，以便深入了解快取效能。透過在該集合上執行下列命令，即可找到特定集合的快取統計資料：

```
db.collection.stats()
```

此命令輸出中的 `cacheStats` 欄位值提供集合的快取統計資料，以及在集合上建立之索引的快取統計資料總計。以下列出這些統計資料：
+ **`collBlksHit`** - 在此集合操作期間從快取讀取的區塊數量。
+ **`collBlksRead`** - 在此集合操作期間從磁碟讀取的區塊數量 （快取遺漏）。
+ **`collHitRatio`** - 此集合的快取命中率 (`100 * [collBlksHit / (collBlksHit + collBlksRead)]`)。
+ **`idxBlksHit`** - 為此集合上建立的任何索引從快取讀取的區塊數量。
+ **`idxBlksRead`** - 此集合上建立的任何索引從磁碟讀取的區塊數量 （快取遺漏）。
+ **`idxHitRatio`** - 在此集合上建立之索引的快取命中率 (`100 * [idxBlksHit / (idxBlksHit + idxBlksRead)]`)。
+ **`lastReset`** - 上次重設這些統計資料的時間。提供的統計資料`db.collection.stats()`會在啟動/停止叢集或向上/向下擴展執行個體時重設。

您也可以使用 `indexStats`命令找到每個索引的 `idxBlksHit`和 `idxBlksRead` 欄位明細。執行下列命令，即可找到索引特定的快取統計資料：

```
db.collection.aggregate([{$indexStats:{}}]).pretty()
```

對於每個索引，您可以在 `cacheStats` 欄位下找到下列快取統計資料：
+ **`blksHit`** - 此索引從快取讀取的區塊數量。
+ **`blksRead`** - 從此索引磁碟讀取的區塊數量。
+ **`blksHitRatio`** - 快取命中率四捨五入到四個小數位數，由 計算`100 * [blksHit / (blksHit + blksRead)]`。

## 如何尋找並終止長時間執行或封鎖的查詢？
<a name="user_diagnostics-query_terminating"></a>

使用者查詢執行緩慢的原因，可能是查詢計畫不佳，或因為資源爭用而遭封鎖。

若要尋找因查詢計畫不佳而造成長時間執行查詢的效率變慢，或因為資源爭用而遭封鎖的查詢，請先使用 `currentOp` 命令。您可以篩選命令，以利減縮要終止的相關查詢清單。您必須具備與長時間執行查詢相關聯的 `opid`，才能夠終止查詢。

以下查詢會使用 `currentOp` 命令來列出所有遭到封鎖或執行超過 10 秒的查詢。

```
db.adminCommand({
    aggregate: 1,
    pipeline: [
        {$currentOp: {}},
        {$match: 
            {$or: [
                {secs_running: {$gt: 10}},
                {WaitState: {$exists: true}}]}},
        {$project: {_id:0, opid: 1, secs_running: 1}}],
    cursor: {}
});
```

接著，您就可以縮減查詢，尋找並終止執行超過 10 秒的查詢 `opid`。

**尋找和終止執行超過 10 秒的查詢**

1. 尋找查詢的 `opid`。

   ```
   db.adminCommand({
       aggregate: 1,
       pipeline: [
           {$currentOp: {}},
           {$match: 
               {$or: 
                   [{secs_running: {$gt: 10}},
                    {WaitState: {$exists: true}}]}}],
       cursor: {}
   });
   ```

   此操作的輸出將會如下所示 (JSON 格式)。

   ```
   {
       "waitedMS" : NumberLong(0),
       "cursor" : {
           "firstBatch" : [
               {
                   "opid" : 24646,
                   "secs_running" : 12 
               }
           ],
           "id" : NumberLong(0),
           "ns" : "admin.$cmd"
       },
       "ok" : 1
   }
   ```

1. 使用 `killOp` 操作終止查詢。

   ```
   db.adminCommand({killOp: 1, op: 24646});
   ```

## 如何查看查詢計畫並最佳化查詢？
<a name="user_diagnostics-query_plan"></a>

查詢的執行速度如果緩慢，可能是由於查詢執行需要完整掃描集合來選擇相關的文件。有時，建立適當的索引能夠使查詢的執行速度更快。若要偵測這種情況並決定建立索引的欄位，請使用 `explain` 命令。

**注意**  
Amazon DocumentDB 在利用分散式、容錯、自我修復儲存系統的專用資料庫引擎上模擬 MongoDB 3.6 API。因此，Amazon DocumentDB 和 MongoDB 之間的查詢計劃和 的輸出`explain()`可能不同。想要控制其查詢計劃的客戶可以使用 `$hint` 運算子強制選取偏好的索引。

請在 `explain` 命令下執行您要改善的查詢，如下所示。

```
db.runCommand({explain: {<query document>}})
```

下面是範例操作。

```
db.runCommand({explain:{
    aggregate: "sample-document",
    pipeline: [{$match: {x: {$eq: 1}}}],
    cursor: {batchSize: 1}}
});
```

此操作的輸出將會如下所示 (JSON 格式)。

```
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "db.test",
        "winningPlan" : {
            "stage" : "COLLSCAN"
        }
    },
    "serverInfo" : {
        "host" : "...",
        "port" : ...,
        "version" : "..."
    },
    "ok" : 1
}
```

上述輸出表示 `$match` 階段需要掃描完整的集合，並確認每個文件中的欄位 `"x"` 皆等於 1。如果集合中有多個文件，則集合掃描速度 (和必然的整體查詢效能) 將非常緩慢。因此，`explain` 命令輸出中的 `"COLLSCAN"` 表示可以透過建立適當的索引來提高查詢效能。

在此範例中，查詢會檢查所有文件中的欄位 `"x"` 是否等於 1。因此建立欄位 `"x"` 的索引，便可讓查詢避免完整集合掃描，並且使用索引加快相關文件傳回。

在欄位 `"x"` 上建立索引後，`explain` 輸出如下所示。

```
{
    "queryPlanner" : {
         "plannerVersion" : 1,
         "namespace" : "db.test",
         "winningPlan" : {
             "stage" : "IXSCAN",
             "indexName" : "x_1",
             "direction" : "forward"
         }
    },
    "serverInfo" : {
        "host" : "...",
        "port" : ...,
        "version" : "..."
    },
    "ok" : 1
}
```

在欄位 `"x"` 上建立索引將使 `$match` 階段能夠使用索引掃描，以減少必須進行評估之述詞 `"x = 1"` 的文件數量。

對於小型集合，如果效能增益微乎其微，Amazon DocumentDB 查詢處理器可以選擇不使用索引。

## 如何查看彈性叢集中的查詢計劃？
<a name="user-diagnostics-ec-query-plan"></a>

若要檢查彈性叢集中的查詢計劃，請使用 `explain`命令。以下是以碎片集合為目標之尋找查詢的範例`explain`操作：

```
db.runCommand(
   {
     explain: { find: "cities", filter: {"name": "Seoul"}}
   }
)
```

**注意**  
Amazon DocumentDB 在專用資料庫引擎上模擬 MongoDB。因此，Amazon DocumentDB 和 MongoDB 之間的查詢計劃和 的輸出`explain()`可能不同。您可以使用 `$hint`運算子來控制查詢計劃，以強制選取偏好的索引。

此操作的輸出看起來可能會類似以下 (JSON 格式）：

```
{
  "queryPlanner" : {
    "elasticPlannerVersion" : 1,
    "winningPlan" : {
      "stage" : "SINGLE_SHARD",
      "shards" : [
        {
          "plannerVersion" : 1,
          "namespace" : "population.cities",
          "winningPlan" : {
            "stage" : "SHARD_MERGE",
            "shards" : [
              {
                "shardName" : "f2cf5cfd-fe9c-40ca-b4e5-298ca0d11111",
                "plannerVersion" : 1,
                "namespace" : "population.cities",
                "winningPlan" : {
                  "stage" : "PARTITION_MERGE",
                  "inputStages" : [
                    {
                      "stage" : "COLLSCAN",
                      "partitionCount" : 21
                    }
                  ]
                }
              },
              {
                "shardName" : "8f3f80e2-f96c-446e-8e9d-aab8c7f22222",
                "plannerVersion" : 1,
                "namespace" : "population.cities",
                "winningPlan" : {
                  "stage" : "PARTITION_MERGE",
                  "inputStages" : [
                    {
                      "stage" : "COLLSCAN",
                      "partitionCount" : 21
                    }
                  ]
                }
              },
              {
                "shardName" : "32c5a06f-1b2b-4af1-8849-d7c4a033333",
                "plannerVersion" : 1,
                "namespace" : "population.cities",
                "winningPlan" : {
                  "stage" : "PARTITION_MERGE",
                  "inputStages" : [
                    {
                      "stage" : "COLLSCAN",
                      "partitionCount" : 22
                    }
                  ]
                }
              }
            ]
          },
          "shardName" : "32c5a06f-1b2b-4af1-8849-d7c4a0f3fb58"
        }
      ]
    }
  },
  "serverInfo" : {
    "host" : "example-4788267630.us-east-1.docdb-elastic.amazonaws.com:27017",
    "version" : "5.0.0"
  },
  "ok" : 1,
  "operationTime" : Timestamp(1695097923, 1)
}
```

上述輸出顯示三個碎片叢集上查詢的`find`查詢計劃。每個碎片都有多個資料分割區，可以有不同的輸入階段。在此範例中，「COLLSCAN」 （集合掃描） 會先在所有分割區上執行，再在每個碎片中的「PARTITION\$1MERGE」階段合併結果。然後將碎片的結果合併到「SHARD\$1MERGE」階段，再傳回用戶端。

## 如何列出執行個體上所有正在執行的操作？
<a name="user_diagnostics-list_queries"></a>

身為使用者或主要使用者，您通常想要列出執行個體上執行的所有目前操作，以進行診斷和故障診斷。(如需有關管理使用者的詳細資訊，請參閱 [管理 Amazon DocumentDB 使用者](security.managing-users.md)。)

使用 `mongo` shell，您可以使用下列查詢列出 Amazon DocumentDB 執行個體上執行的所有操作。

```
db.adminCommand({currentOp: 1, $all: 1});
```

此查詢會傳回一份完整清單，內含所有使用者查詢和執行個體目前正在操作的內部系統任務。

此操作的輸出將會如下所示 (JSON 格式)。

```
{
    "inprog" : [
        {
            "desc" : "INTERNAL"
        },
        {
            "desc" : "TTLMonitor",
            "active" : false
        },
        {
            "client" : ...,
            "desc" : "Conn",
            "active" : true,
            "killPending" : false,
            "opid" : 195,
            "ns" : "admin.$cmd",
            "command" : {
                "currentOp" : 1,
                "$all" : 1
            },
            "op" : "command",
            "$db" : "admin",
            "secs_running" : 0,
            "microsecs_running" : NumberLong(68),
            "clientMetaData" : {
            "application" : {
                "name" : "MongoDB Shell"
            },
            "driver" : {
                ...
            },
            "os" : {
                ...
            }
          }
       },
       {
          "desc": "GARBAGE_COLLECTION",
          "garbageCollection": {
             "databaseName": "testdb",
             "collectionName": "testCollectionA"
          },
          "secs_running": 3,
          "microsecs_running": NumberLong(3123456)
       },
       {
          "desc": "GARBAGE_COLLECTION",
          "garbageCollection": {
             "databaseName": "testdb",
             "collectionName": "testCollectionB"
          },
          "secs_running": 4,
          "microsecs_running": NumberLong(4123456)
       }
    ],
    "ok" : 1
}
```

以下是 `"desc"` 欄位的有效值：
+ **INTERNAL** — 內部系統任務，例如游標清除或過時的使用者清除任務。
+ **TTLMonitor** — 存留時間 (TTL) 監控執行緒。其執行狀態會反映在 `"active"` 欄位。
+ **GARBAGE\$1COLLECTION** — 內部垃圾收集器執行緒。
+ **CONN** — 使用者查詢。
+ **CURSOR** — 操作是等待使用者呼叫「getMore」命令以取得下一批結果的閒置游標。在此狀態下，游標會耗用記憶體，但不會耗用任何運算。

前述輸出也會列出系統中執行的所有使用者查詢。每個使用者查詢會在資料庫和集合的內容中執行，這兩者的聯集稱為*命名空間*。`"ns"` 欄位會提供每個使用者查詢的命名空間。

有時您需要列出在特定命名空間中執行的所有使用者查詢。因此，之前的輸出必須經過 `"ns"` 欄位篩選。下面是為達到篩選輸出的範例查詢。查詢會列出資料庫 `"db"` 和集合 `"test"` (即 `"db.test"` 命名空間) 中目前正在執行的所有使用者查詢。

```
db.adminCommand({aggregate: 1,
    pipeline: [{$currentOp: {allUsers: true, idleConnections: true}},
               {$match: {ns: {$eq: "db.test"}}}],
    cursor: {}
});
```

身為系統的主要使用者，您可以看到所有使用者和所有內部系統任務的查詢。所有其他使用者都只能查看其各自查詢。

如果查詢和內部系統任務的總數超過預設批次處理游標大小，則 `mongo` 殼層將自動產生迭代器物件 `'it'` 以查看其餘結果。請持續執行命令 `'it'`，直到所有結果都已用盡。

## 如何知道查詢何時進行？
<a name="user_diagnostics-query_progressing"></a>

使用者查詢執行緩慢的原因，可能是查詢計畫不佳，或因為資源爭用而遭封鎖。偵錯此類查詢需要進行多個步驟，而其有時需要多次執行相同的步驟。

偵錯的第一步是列出長時間執行或封鎖的所有查詢。下列查詢列出執行超過 10 秒或等待資源的所有使用者查詢。

```
db.adminCommand({aggregate: 1,
                 pipeline: [{$currentOp: {}},
                            {$match: {$or: [{secs_running: {$gt: 10}},
                                            {WaitState: {$exists: true}}]}},
                            {$project: {_id:0,
                                        opid: 1,
                                        secs_running: 1,
                                        WaitState: 1,
                                        blockedOn: 1,
                                        command: 1}}],
                 cursor: {}
                });
```

請定期重複上述查詢，判斷查詢清單是否變更，並找出長時間執行的查詢或遭封鎖的查詢。

如果您查詢的輸出文件中包含 `WaitState` 欄位，則表示資源爭用是造成查詢執行速度緩慢或遭封鎖的原因。資源爭用的可能成因是 IO、內部系統任務或其他使用者查詢。

此操作的輸出將會如下所示 (JSON 格式)。

```
{
    "waitedMS" : NumberLong(0),
    "cursor" : {
        "firstBatch" : [
            {
                "opid" : 201,
                "command" : {
                    "aggregate" : ...
                },
                "secs_running" : 208,
                "WaitState" : "IO"
            }
        ],
        "id" : NumberLong(0),
        "ns" : "admin.$cmd"
    },
    "ok" : 1
}
```

如果同時在相同執行個體上執行的不同集合中有多個查詢，或執行個體大小對執行查詢的資料集而言太小，則 I/O 可能成為瓶頸。如果查詢是唯讀查詢，則您可以在不同複本上分隔每個集合的查詢，有效緩解這個情況。若是跨不同集合的並行更新，或執行個體的大小對資料集而言太小，則您可以向上擴展執行個體來進行緩解。

如果資源爭用是由其他使用者查詢所引起，則輸出文件中的 `"blockedOn"` 欄位將包含影響此查詢之查詢的 `"opid"`。使用 `"opid"` 追蹤所有查詢的 `"WaitState"` 和 `"blockedOn"` 欄位鏈結，以在鏈結的前端尋找查詢。

如果鏈結前端的任務為內部任務，則唯一的緩解措施是終止查詢，並在一段時間後重新執行該查詢。

在以下的範例輸出中，其尋找查詢在另一個任務擁有的集合鎖上遭到封鎖。

```
{
    "inprog" : [
        {
            "client" : "...",
            "desc" : "Conn",
            "active" : true,
            "killPending" : false,
            "opid" : 75,
            "ns" : "...",
            "command" : {
                "find" : "...",
                "filter" : {

                }
            },
            "op" : "query",
            "$db" : "test",
            "secs_running" : 9,
            "microsecs_running" : NumberLong(9449440),
            "threadId" : 24773,
            "clientMetaData" : {
                "application" : {
                   "name" : "MongoDB Shell"
                },
                "driver" : {
                    ...
                },
                "os" : {
                    ...
                }
            },
            "WaitState" : "CollectionLock",
            "blockedOn" : "INTERNAL"
        },
        {
            "desc" : "INTERNAL"
        },
        {
            "client" : "...",
            ...
            "command" : {
                "currentOp" : 1
            },
            ...
        }
    ],
    "ok" : 1
}
```

如果 `"WaitState"` 具有值 `"Latch"`、`"SystemLock"`、`"BufferLock"`、`"BackgroundActivity"` 或 `"Other"`，則資源爭用來源為內部系統任務。如果情況持續很長一段時間，則唯一的緩解措施是終止該查詢，並在一段時間後重新執行該查詢。

## 如何判斷系統突然緩慢執行的原因？
<a name="user_diagnostics-speed_change"></a>

下面列出系統變慢的一些常見原因：
+ 並行查詢之間的資源爭用過多 
+ 作用中並行查詢的數量會隨著時間增加
+ 內部系統任務，例如 `"GARBAGE_COLLECTION"`

若要隨著時間監控系統使用量，請定期執行下列 `"currentOp"` 查詢，並將結果輸出到外部存放區。該查詢會計算系統中每個命名空間的查詢和操作數量。接著，您就可以分析系統使用量結果來了解系統負載，並採取適當行動。

```
db.adminCommand({aggregate: 1,
                 pipeline: [{$currentOp: {allUsers: true, idleConnections: true}},
                            {$group: {_id: {desc: "$desc", ns: "$ns", WaitState: "$WaitState"}, count: {$sum: 1}}}],
                 cursor: {}
                });
```

此查詢會傳回每個命名空間中執行之所有查詢和所有內部系統任務的彙總，以及每個命名空間專屬的等待狀態數量。

此操作的輸出將會如下所示 (JSON 格式)。

```
{
    "waitedMS" : NumberLong(0),
    "cursor" : {
        "firstBatch" : [
            {
                "_id" : {
                    "desc" : "Conn",
                    "ns" : "db.test",
                    "WaitState" : "CollectionLock"
                },
               "count" : 2
            },
            {
                "_id" : {
                    "desc" : "Conn",
                    "ns" : "admin.$cmd"
                },
                "count" : 1
            },
            {
                "_id" : {
                    "desc" : "TTLMonitor"
                },
                "count" : 1
            }
        ],
        "id" : NumberLong(0),
        "ns" : "admin.$cmd"
    },
    "ok" : 1
}
```

在前述輸出中，命名空間 `"db.test"` 中有 2 個使用者查詢在集合鎖定上遭到封鎖：其中 1 個查詢位於命名空間 `"admin.$cmd"` 中，另一個位於內部 `"TTLMonitor"` 任務中。

如果輸出指出許多查詢處於封鎖等待狀態，請參閱[如何尋找並終止長時間執行或封鎖的查詢？](#user_diagnostics-query_terminating)

## 如何判斷一或多個叢集執行個體上高 CPU 使用率的原因？
<a name="user_diagnostics-cpu_utilization"></a>

下列各節可協助您識別高執行個體 CPU 使用率的原因。結果可能因工作負載而有差異。
+ 若要判斷執行個體突然執行緩慢的原因，請參閱[如何判斷系統突然緩慢執行的原因？](#user_diagnostics-speed_change) 
+ 若要識別和終止特定執行個體的長時間執行查詢，請參閱[如何尋找並終止長時間執行或封鎖的查詢？](#user_diagnostics-query_terminating) 
+ 若要了解查詢是否正在進行，請參閱[如何知道查詢何時進行？](#user_diagnostics-query_progressing) 
+ 若要判斷查詢需要長期執行時間的原因，請參閱[如何查看查詢計畫並最佳化查詢？](#user_diagnostics-query_plan)
+ 若要追蹤隨時間演進的長時間執行查詢，請參閱[分析 Amazon DocumentDB 操作](profiling.md)。

根據造成高執行個體 CPU 使用率的原因，執行下列一項或多項動作可能有所幫助。
+ 如果主要執行個體顯示高 CPU 使用率，但複本執行個體未顯示同樣情況，則請考慮透過用戶端讀取偏好設定 (例如 `secondaryPreferred`)，將讀取流量分配至所有複本。如需詳細資訊，請參閱[以複本集的形式連線至 Amazon DocumentDB](connect-to-replica-set.md)。

  使用複本進行讀取時，因為主要執行個體可以處理更多寫入流量，進而有效提升叢集資源的使用效能。來自複本的讀取最終會保持一致。
+ 如果寫入工作負載的結果是造成高 CPU 使用率，則將叢集執行個體的大小變更為較大的執行個體類型，將會增加可用於服務工作負載的 CPU 核心數量。如需詳細資訊，請參閱[執行個體](what-is.md#what-is-db-instances)及[執行個體類別規格](db-instance-classes.md#db-instance-class-specs)。
+ 如果所有叢集執行個體都呈現高 CPU 使用率，且工作負載使用複本進行讀取，則新增更多複本到叢集時，可供讀取流量使用的資源將會增加。如需詳細資訊，請參閱[將 Amazon DocumentDB 執行個體新增至叢集](db-instance-add.md)。

## 如何判斷執行個體上的開啟游標？
<a name="user_diagnostics-open_cursors"></a>

連線至 Amazon DocumentDB 執行個體時，您可以使用 命令`db.runCommand("listCursors")`列出該執行個體上的開啟游標。根據執行個體類型，指定 Amazon DocumentDB 執行個體上在任何指定時間最多可開啟 4，560 個作用中游標。我們通常建議關閉不再使用的游標，因為游標會使用執行個體上的資源，且有數目上限的限制。如需特定限制[Amazon DocumentDB 配額和限制](limits.md)，請參閱 。

```
db.runCommand("listCursors") 
```

## 如何判斷目前的 Amazon DocumentDB 引擎版本？
<a name="user_diagnostics-engine_version"></a>

若要判斷您目前的 Amazon DocumentDB 引擎版本，請執行下列命令。

```
db.runCommand({getEngineVersion: 1})
```

此操作的輸出將會如下所示 (JSON 格式)。

```
{ "engineVersion" : "2.x.x", "ok" : 1 }
```

**注意**  
Amazon DocumentDB 3.6 的引擎版本為 1.x.x，Amazon DocumentDB 4.0 的引擎版本為 2.x.x，Amazon DocumentDB 5.0 的引擎版本為 3.x.x，Amazon DocumentDB 8.0 的引擎版本為 4.x.x。

## 如何分析索引用量並識別未使用的索引？
<a name="user-diag-index-usage"></a>

若要識別指定集合的索引，請執行下列命令：

```
db.collection.getIndexes()
```

若要分析在集合上執行的操作期間使用多少索引，可以使用 `collStats`和 `indexStats`命令。若要檢視使用索引執行的掃描總數 （索引掃描） 與不使用索引執行的掃描總數 （集合掃描），請執行下列命令：

```
db.collection.stats()
```

此命令的輸出包含下列值：
+ **`idxScans`** - 在此集合上使用索引執行的掃描次數。
+ **`collScans`** - 在此集合上執行的掃描數目，而不使用索引。這些掃描會涉及逐一查看集合中的文件。
+ **`lastReset`** - 這些計數器上次重設的時間。此命令提供的統計資料會在啟動/停止叢集或向上/向下擴展執行個體時重設。

您可以在下列命令的輸出中找到每個索引的使用量明細。最佳實務是定期識別和移除未使用的索引，以提高效能並降低成本，因為它消除了用於維護索引的不必要的運算、儲存和 I/O。

```
db.collection.aggregate([{$indexStats:{}}]).pretty()
```

此命令的輸出為集合上建立的每個索引提供下列值：
+ **`ops`** - 使用索引的操作數目。如果您的工作負載已執行足夠長的時間，而且您確信您的工作負載處於穩定狀態，`ops` 的零值表示完全不使用索引。
+ **`numDocsRead`** - 在此索引操作期間讀取的文件數量。
+ **`since`** - Amazon DocumentDB 開始收集索引用量統計資料以來的時間，通常是自上次資料庫重新啟動或維護動作以來的值。
+ **`size`** - 此索引的大小，以位元組為單位。

下列範例是執行上述命令的範例輸出：

```
{
    "name" : "_id_",
    "key" : {
        "_id" : 1
    },
    "host" : "example-host.com:12345",
    "size" : NumberLong(...),
    "accesses" : {
        "ops" : NumberLong(...),
        "docsRead" : NumberLong(...),
        "since" : ISODate("...")
    },
    "cacheStats" : {
        "blksRead" : NumberLong(...),
        "blksHit" : NumberLong(...),
        "hitRatio" : ...
    }
}
{
    "name" : "x_1",
    "key" : {
        "x" : 1
    },
    "host" : "example-host.com:12345",
    "size" : NumberLong(...),
    "accesses" : {
        "ops" : NumberLong(...),
        "docsRead" : NumberLong(...),
        "since" : ISODate("...")
    },
    "cacheStats" : {
        "blksRead" : NumberLong(...),
        "blksHit" : NumberLong(...),
        "hitRatio" : ...
    }
}
```

若要判斷集合的整體索引大小，請執行下列命令：

```
db.collection.stats()
```

若要刪除未使用的索引，請執行下列命令：

```
db.collection.dropIndex("indexName")
```

## 如何識別缺少的索引？
<a name="user_diagnostics-identify_missing_indexes"></a>

您可以使用 [Amazon DocumentDB 分析工具來記錄慢查詢](https://docs.aws.amazon.com//documentdb/latest/developerguide/profiling.html)。在慢速查詢日誌中重複出現查詢，可能表示需要額外的索引來改善該查詢的效能。

您可以透過尋找具有至少執行一個`COLLSCAN`階段之一或多個階段的長時間執行查詢來識別有用索引的機會，這表示查詢階段必須讀取集合中的每個文件，才能提供查詢的回應。

下列範例顯示在大型集合上執行的計程車乘車查詢。

```
db.rides.count({"fare.totalAmount":{$gt:10.0}}))
```

為了執行這個範例，查詢必須執行集合掃描 (即讀取集合中的每個文件)，因為該 `fare.totalAmount` 欄位上沒有索引。此查詢的 Amazon DocumentDB 分析工具輸出如下所示：

```
{
    ...
    "cursorExhausted": true,
    "nreturned": 0, 
    "responseLength": 0,
    "protocol": "op_query",
    "millis": 300679,
    "planSummary": "COLLSCAN",
    "execStats": {
        "stage": "COLLSCAN",
        "nReturned": "0",
        "executionTimeMillisEstimate": "300678.042"
    },
    "client": "172.31.5.63:53878",
    "appName": "MongoDB Shell",
    "user": "example"
}
```

為了加快這個例子中的查詢，您可在 `fare.totalAmount` 建立一個索引，如下圖所示。

```
db.rides.createIndex( {"fare.totalAmount": 1}, {background: true} )
```

**注意**  
在前景中建立的索引 (也就是說，如果建立索引時未提供 `{background:true}` 選項) 會採用獨佔寫入鎖定，這樣可以防止應用程式在索引建立完成之前將資料寫入集合。在生產叢集上建立索引時，請注意這項潛在影響。建立索引時，建議設定 `{background:true}`。

一般而言，您會希望在具有高基數 (例如，大量唯一值) 的欄位上建立索引。在低基數的欄位上建立索引可能會導致有大型索引未使用。建立查詢計劃時，Amazon DocumentDB 查詢最佳化工具會考慮集合的整體大小和索引的選擇性。有時候，您會看到查詢處理器選擇一個 `COLLSCAN`，即使索引已存在。當查詢處理器預估，相較於掃描整個集合，利用索引並不會產生效能優勢時，就會發生這種情況。如果您想強制查詢處理器利用一個特定索引，您可以使用 `hint()` 運算子，如下圖所示。

```
db.collection.find().hint("indexName")
```

## 如何判斷資料庫集合膨脹？
<a name="performance-collection-bloat"></a>

當集合的大小因資料庫頁面內累積過時或過時的文件或分段而變大時，就會發生集合膨脹。報告的百分比代表未來文件可以使用的文件空間量。此膨脹會耗用緩衝區快取和儲存體中的空間。若要移除膨脹，集合必須透過傾印/還原重新載入，或在維護時段期間使用遷移回送和切換。

**Example 範例**  
執行下列命令來判斷集合的未使用儲存：  

```
db.runCommand({collStats:'coll'})
```
結果如下所示：  

```
{
        "ns" : "test.coll",
        "count" : 7500,
        "size" : 23250,
        "avgObjSize" : 31,
        "storageSize" : 106496,
        "unusedStorageSize" : {
                "unusedBytes" : 16384,
                "unusedPercent" : 25.12
        },
        "compression" : {
                "enable" : false
        },
        "capped" : false,
        "nindexes" : 1,
        "totalIndexSize" : 57344,
        "indexSizes" : {
                "_id_" : 57344
        },
        "collScans" : 4,
        "idxScans" : 10000,
        "opCounter" : {
                "numDocsIns" : 1000,
                "numDocsUpd" : 0,
                "numDocsDel" : 250
        },
        "cacheStats" : {
                "collBlksHit" : 3570,
                "collBlksRead" : 8,
                "collHitRatio" : 99.7765,
                "idxBlksHit" : 12293,
                "idxBlksRead" : 6,
                "idxHitRatio" : 99.9513
        },
        "lastReset" : "2024-12-18 00:30:21.552019+00",
        "ok" : 1,
        "operationTime" : Timestamp(1734632375, 1)
}
```

## 有用的查詢摘要
<a name="user_diagnostics-useful_queries"></a>

下列查詢有助於監控 Amazon DocumentDB 中的效能和資源使用率。
+ 使用下列命令來檢視特定集合的統計資料，包括操作計數器、快取統計資料、存取統計資料和大小統計資料：

  ```
  db.collection.stats()
  ```
+ 使用下列命令來檢視在集合上建立的每個索引的統計資料，包括索引的大小、索引特定的快取統計資料和索引用量統計資料：

  ```
  db.collection.aggregate([{$indexStats:{}}]).pretty()
  ```
+ 使用以下查詢來列出所有活動。

  ```
  db.adminCommand({currentOp: 1, $all: 1});
  ```
+ 下面程式碼會列出所有長時間執行或遭封鎖的查詢。

  ```
  db.adminCommand({aggregate: 1,
                   pipeline: [{$currentOp: {}},
                              {$match: {$or: [{secs_running: {$gt: 10}},
                                              {WaitState: {$exists: true}}]}},
                              {$project: {_id:0,
                                          opid: 1,
                                          secs_running: 1,
                                          WaitState: 1,
                                          blockedOn: 1,
                                          command: 1}}],
                   cursor: {}
                  });
  ```
+ 下列程式碼會終止查詢。

  ```
  db.adminCommand({killOp: 1, op: <opid of running or blocked query>});
  ```
+ 使用下列程式碼來取得系統狀態的彙總檢視。

  ```
  db.adminCommand({aggregate: 1,
                   pipeline: [{$currentOp: {allUsers: true, idleConnections: true}},
                              {$group: {_id: {desc: "$desc", ns: "$ns", WaitState: "$WaitState"}, count: {$sum: 1}}}],
                   cursor: {}
                  });
  ```