

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

# Amazon DocumentDB 故障診斷
<a name="troubleshooting"></a>

下列各節提供有關如何對使用 Amazon DocumentDB 時可能遇到的問題進行故障診斷的資訊 （具有 MongoDB 相容性）。

**Topics**
+ [連線問題](troubleshooting.connecting.md)
+ [索引](troubleshooting.index-creation.md)
+ [效能和資源使用率](user_diagnostics.md)
+ [垃圾回收](garbage-collection.md)

# 連線問題疑難排解
<a name="troubleshooting.connecting"></a>

連線時發生問題？ 以下是一些常見的案例，以及如何解決這些案例。

**主題**
+ [無法連線至 Amazon DocumentDB 端點](#troubleshooting-connecting)
+ [測試與 Amazon DocumentDB 執行個體的連線](#troubleshooting.testing-connection)
+ [連線至無效的端點](#troubleshooting.invalid-endpoint)
+ [影響連線數量的驅動程式組態](#troubleshooting.driver.config)

## 無法連線至 Amazon DocumentDB 端點
<a name="troubleshooting-connecting"></a>

當您嘗試連線至 Amazon DocumentDB 時，下列是您可能會收到的最常見錯誤訊息之一。

```
connecting to: mongodb://docdb-2018-11-08-21-47-27.cluster-ccuszbx3pn5e.us-east-
1.docdb.amazonaws.com:27017/
2018-11-14T14:33:46.451-0800 W NETWORK [thread1] Failed to connect to
172.31.91.193:27017 after 5000ms milliseconds, giving up.
2018-11-14T14:33:46.452-0800 E QUERY [thread1] Error: couldn't connect to server
docdb-2018-11-08-21-47-27.cluster-ccuszbx3pn5e.us-east-1.docdb.amazonaws.com:27017,
connection attempt failed :
connect@src/mongo/shell/mongo.js:237:13
@(connect):1:6
exception: connect failed
```

此錯誤訊息通常表示您的用戶端 （此範例中的 mongo shell) 無法存取 Amazon DocumentDB 端點。這可能有幾個原因：

**Topics**
+ [從公有端點連線](#troubleshooting.cannot-connect.public-endpoints)
+ [跨區域連線](#troubleshooting.cannot-connect.different-regions)
+ [從不同的 Amazon VPCs 連線](#troubleshooting.cannot-connect.different-vpcs)
+ [安全群組封鎖傳入連線](#troubleshooting.cannot-connect.inbound-not-allowed)
+ [Java Mongo 驅動程式讀取偏好設定問題](#troubleshooting-cannot-connect-java-mongo-issue)

### 從公有端點連線
<a name="troubleshooting.cannot-connect.public-endpoints"></a>

**您正在嘗試直接從筆記型電腦或本機開發機器連線至 Amazon DocumentDB 叢集。**

嘗試直接從您的筆記型電腦或本機開發機器等公有端點連線至 Amazon DocumentDB 叢集將會失敗。Amazon DocumentDB 是僅限虛擬私有雲端 (VPC)，目前不支援公有端點。因此，您無法從筆記型電腦或 VPC 外部的本機開發環境直接連線至 Amazon DocumentDB 叢集。

若要從 Amazon VPC 外部連線至 Amazon DocumentDB 叢集，您可以使用 SSH 通道。如需詳細資訊，請參閱[從 Amazon VPC 外部連線至 Amazon DocumentDB 叢集](connect-from-outside-a-vpc.md)。此外，如果您的開發環境位於不同的 Amazon VPC 中，您也可以使用 VPC 對等互連，並從相同區域或不同區域的另一個 Amazon VPC 連線至您的 Amazon DocumentDB 叢集。

### 跨區域連線
<a name="troubleshooting.cannot-connect.different-regions"></a>

**您嘗試連線到另一個區域中的 Amazon DocumentDB 叢集。**

如果您嘗試從叢集區域以外的 區域中的 Amazon EC2 執行個體連線至 Amazon DocumentDB 叢集，例如，嘗試從美國西部 （奧勒岡） 區域 (us-west-2) 連線至美國東部 （維吉尼亞北部） 區域 (us-east-1) 中的叢集，連線將會失敗。

若要驗證 Amazon DocumentDB 叢集的區域，請執行下列命令。區域在端點中。

```
aws docdb describe-db-clusters \
   --db-cluster-identifier sample-cluster \
   --query 'DBClusters[*].Endpoint'
```

此操作的輸出將會如下所示。

```
[
    "sample-cluster.node.us-east-1.docdb.amazonaws.com"
]
```

為了驗證您的 EC2 執行個體的區域，請執行以下命令。

```
 aws ec2 describe-instances \
     --query 'Reservations[*].Instances[*].Placement.AvailabilityZone'
```

此操作的輸出將會如下所示。

```
[
    [
        "us-east-1a"
    ]
]
```

### 從不同的 Amazon VPCs 連線
<a name="troubleshooting.cannot-connect.different-vpcs"></a>

**您嘗試從與您部署叢集的 Amazon VPC 不同的 VPC 連線至 Amazon DocumentDB 叢集。**

如果您的 Amazon DocumentDB 叢集和 Amazon EC2 執行個體都位於相同的 Amazon VPC 中 AWS 區域，但不在相同的 Amazon VPC 中，除非在兩個 Amazon VPCs 之間啟用 VPC 對等互連，否則您無法直接連線至 Amazon DocumentDB 叢集。

若要驗證 Amazon DocumentDB 執行個體的 Amazon VPC，請執行下列命令。

```
aws docdb describe-db-instances \
   --db-instance-identifier sample-instance \
   --query 'DBInstances[*].DBSubnetGroup.VpcId'
```

若要驗證 Amazon EC2 執行個體的 Amazon VPC，請執行下列命令。

```
aws ec2 describe-instances \
   --query 'Reservations[*].Instances[*].VpcId'
```

### 安全群組封鎖傳入連線
<a name="troubleshooting.cannot-connect.inbound-not-allowed"></a>

**您嘗試連線到 Amazon DocumentDB 叢集，而叢集的安全群組不允許叢集連接埠上的傳入連線 （預設連接埠：27017)。**

假設您的 Amazon DocumentDB 叢集和 Amazon EC2 執行個體都位於相同的區域和 Amazon VPC，並使用相同的 Amazon VPC 安全群組。如果您無法連線至 Amazon DocumentDB 叢集，可能原因為叢集的安全群組 （也就是防火牆） 不允許您為 Amazon DocumentDB 叢集選擇的連接埠 （預設連接埠為 27017) 上的傳入連線。

若要驗證 Amazon DocumentDB 叢集的連接埠，請執行下列命令。

```
aws docdb describe-db-clusters \
   --db-cluster-identifier sample-cluster \
   --query 'DBClusters[*].[DBClusterIdentifier,Port]'
```

若要取得叢集的 Amazon DocumentDB 安全群組，請執行下列命令。

```
aws docdb describe-db-clusters \
   --db-cluster-identifier sample-cluster \
   --query 'DBClusters[*].[VpcSecurityGroups[*],VpcSecurityGroupId]'
```

若要檢查安全群組的傳入規則，請參閱 Amazon EC2 文件中的下列主題：
+ [ 授權 Linux 執行個體的傳入流量](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/authorizing-access-to-an-instance.html)
+ [ 授權 Windows 執行個體的傳入流量](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/authorizing-access-to-an-instance.html)

### Java Mongo 驅動程式讀取偏好設定問題
<a name="troubleshooting-cannot-connect-java-mongo-issue"></a>

**除非重新啟動，否則不會遵守用戶端讀取偏好設定，而且某些用戶端無法在容錯移轉後寫入 Amazon DocumentDB。**

此問題在 Java Mongo Driver 3.7.x 中首次發現，發生在用戶端使用 建立與 Amazon DocumentDB 的連線`MongoClientSettings`，特別是鏈結`applyToClusterSettings`方法時。MongoClient 叢集設定可以使用幾種不同的方法來定義，例如 `hosts()`、 `requiredReplicaSetName()`和 `mode()`。

 當用戶端在 `hosts()`方法中只指定一個主機時，模式會設定為 `ClusterConnectionMode.SINGLE`而非 `ClusterConnectionMode.MULTIPLE` 這會讓用戶端忽略讀取偏好設定，並只連線到 中設定的伺服器`hosts()`。因此，即使用戶端設定初始化如下，所有讀取仍會移至主要 而非次要 。

```
final ServerAddress serverAddress0 = new ServerAddress("cluster-endpoint", 27317));
    final MongoCredential credential = MongoCredential.createCredential("xxx",
            "admin", "xxxx".toCharArray());
    final MongoClientSettings settings = MongoClientSettings.builder()
            .credential(credential)
            .readPreference(ReadPreference.secondaryPreferred())
            .retryWrites(false)
            .applyToSslSettings(builder -> builder
                    .enabled(false))
            .applyToClusterSettings(builder -> builder.hosts(
                            Arrays.asList(serverAddress0
                            ))
                    .requiredReplicaSetName("rs0"))
            .build();
    MongoClient mongoClient = MongoClients.create(settings);
```

**容錯移轉案例**

使用上述用戶端連線設定，如果叢集寫入器端點有容錯移轉和延遲 DNS 記錄更新，用戶端仍會嘗試向舊寫入器發出寫入 （現在容錯移轉後的讀取器）。這會導致伺服器端錯誤 （非主要），Java 驅動程式未適當處理 （這仍在調查中）。因此，用戶端可能會處於錯誤狀態，直到應用程式伺服器重新啟動為止。

有兩種解決方法：
+ 透過連線字串連線至 Amazon DocumentDB 的用戶端不會發生此問題，因為 `ClusterConnectionMode`會在設定讀取偏好設定`MULTIPLE`時設定為 。

  ```
  MongoClientURI mongoClientURI = new MongoClientURI("mongodb://usr:pass:cluster-endpoint:27317/test?ssl=false&replicaSet=rs0&readpreference=secondaryPreferred");
  MongoClient mongoClient = MongoClients.create(mongoClientURI.getURI());
  ```

  或搭配 `applyConnectionString`方法使用`MongoClientSettings`建置器。

  ```
  final MongoClientSettings settings = MongoClientSettings.builder()
          .credential(credential)
          .applyConnectionString(new ConnectionString("usr:pass:cluster-endpoint:27317/test?ssl=false&replicaSet=rs0&readpreference=secondaryPreferred"))
          .retryWrites(false)
          .applyToSslSettings(builder → builder
                  .enabled(false))
          .build();
  MongoClient mongoClient = MongoClients.create(settings);
  ```
+ 明確`ClusterConnectionMode`設定為 `MULTIPLE`。這只有在使用 `applyToClusterSettings`和 時才需要`hosts().size() == 1`。

  ```
  final ServerAddress serverAddress0 = new ServerAddress("cluster-endpoint", 27317));
  final MongoCredential credential = MongoCredential.createCredential("xxx","admin", "xxxx".toCharArray());
  final MongoClientSettings settings = MongoClientSettings.builder()
      .credential(credential)
      .readPreference(ReadPreference.secondaryPreferred())
      .retryWrites(false)
      .applyToSslSettings(builder → builder
      .enabled(false))
      .applyToClusterSettings(builder → builder
                  .hosts(Arrays.asList(serverAddress0))
                  .requiredReplicaSetName("rs0"))
                  .mode(ClusterConnectionMode.MULTIPLE))
      .build();
  MongoClient mongoClient = MongoClients.create(settings);
  ```

## 測試與 Amazon DocumentDB 執行個體的連線
<a name="troubleshooting.testing-connection"></a>

您可以使用通用的 Linux 或 Windows 工具來測試您的叢集連線。

 從 Linux 或 Unix 終端機測試連線，方法是輸入下列命令 (以端點取代 `cluster-endpoint`，以及以執行個體的連接埠取代 `port`)：

```
nc -zv cluster-endpoint port 
```

以下是範例操作和傳回值的範例：

```
nc -zv docdbTest.d4c7nm7stsfc0.us-west-2.docdb.amazonaws.com 27017
   
Connection to docdbTest.d4c7nm7stsfc0.us-west-2.docdb.amazonaws.com 27017 port [tcp/*] succeeded!
```

## 連線至無效的端點
<a name="troubleshooting.invalid-endpoint"></a>

連線至 Amazon DocumentDB 叢集並使用無效的叢集端點時，會出現類似以下的錯誤。

```
mongo --ssl \
   --host sample-cluster.node.us-east-1.docdb.amazonaws.com:27017 \
   --sslCAFile global-bundle.pem \
   --username <user-name> \
   --password <password>
```

輸出如下：

```
MongoDB shell version v3.6
connecting to: mongodb://sample-cluster.node.us-east-1.docdb.amazonaws.com:27017/
2018-11-14T17:21:18.516-0800 I NETWORK [thread1] getaddrinfo("sample-cluster.node.us-east-1.docdb.amazonaws.com") failed: 
nodename nor servname provided, or not known 2018-11-14T17:21:18.537-0800 E QUERY [thread1] Error: couldn't initialize
connection to host sample-cluster.node.us-east-1.docdb.amazonaws.com, address is invalid :
connect@src/mongo/shell/mongo.js:237:13@(connect):1:6
exception: connect failed
```

若要取得有效的叢集端點，請執行下列命令：

```
aws docdb describe-db-clusters \
   --db-cluster-identifier sample-cluster \
   --query 'DBClusters[*].[Endpoint,Port]'
```

若要取得有效的執行個體端點，請執行下列命令：

```
aws docdb describe-db-instances \
   --db-instance-identifier sample-instance \
   --query 'DBInstances[*].[Endpoint.Address,Endpoint.Port]'
```

如需詳細資訊，請參閱[了解 Amazon DocumentDB 端點](endpoints.md)。

## 影響連線數量的驅動程式組態
<a name="troubleshooting.driver.config"></a>

使用用戶端驅動程式連線至 Amazon DocumentDB 叢集時，請務必考慮`maxPoolSize`組態參數。此`maxPoolSize`設定決定用戶端驅動程式在其連線集區中將維持的最大連線數。

# 索引故障診斷
<a name="troubleshooting.index-creation"></a>

下列主題討論，如果您的索引或背景索引建置失敗，怎麼辦。

**Topics**
+ [索引建置失敗](#troubleshooting.index-build-fails)
+ [背景索引建置延遲問題和失敗](#troubleshooting.background-index-build-fails)
+ [資料庫索引膨脹](#troubleshooting-database-bloat)

## 索引建置失敗
<a name="troubleshooting.index-build-fails"></a>

Amazon DocumentDB 會使用執行個體上的本機儲存體做為索引建立程序的一部分。您可以使用 **FreeLocalStorage** CloudWatch 指標 () 監控此磁碟用量`CloudWatch -> Metrics -> DocDB -> Instance Metrics`。當索引建置使用所有本機磁碟並失敗時，您將會收到錯誤。將資料遷移至 Amazon DocumentDB 時，建議您先建立索引，然後插入資料。如需遷移策略和建立索引的詳細資訊，請參閱[遷移至 Amazon DocumentDB](docdb-migration.md)《Amazon DocumentDB 文件》中的 和部落格：[使用離線方法從 MongoDB 遷移至 Amazon DocumentDB](https://aws.amazon.com/blogs/database/migrate-from-mongodb-to-amazon-documentdb-using-the-offline-method/)。

在現有叢集上建立索引時，如果索引建置耗時超過預期或失敗，建議您擴展執行個體以建立索引，然後在建立索引之後縮減。Amazon DocumentDB 可讓您使用 AWS 管理主控台 或 ，在幾分鐘內快速擴展執行個體大小 AWS CLI。如需詳細資訊，請參閱[管理執行個體類別](db-instance-classes.md)。透過每秒執行個體定價，您只需支付使用的資源，以秒計費。

## 背景索引建置延遲問題和失敗
<a name="troubleshooting.background-index-build-fails"></a>

Amazon DocumentDB 中的背景索引建置不會啟動，除非在索引建置啟動之前啟動的主要執行個體上的所有查詢都已完成執行。如果有長時間執行的查詢，背景索引建置會封鎖，直到查詢完成，因此可能需要比預期更長的時間才能完成。即使集合是空的，也是如此。

前景索引建置不會顯示相同的封鎖行為。相反地，前景索引組建會對集合進行獨佔鎖定，直到索引組建完成為止。因此，為了在空集合上建立索引，並避免封鎖任何長時間執行的查詢，我們建議您使用前景索引組建。

**注意**  
Amazon DocumentDB 僅允許在任何指定時間在集合上建立一個背景索引組建。如果在背景索引建置期間 DDL (資料定義語言) 操作 (如 `createIndex()` 或 `dropIndex()`) 發生於同一個集合，則背景索引建置會失敗。

## 資料庫索引膨脹
<a name="troubleshooting-database-bloat"></a>

Amazon DocumentDB 使用多版本並行控制 (MVCC) 來管理並行交易。刪除或更新文件時，其先前的版本會保留在集合和索引中為「無效」版本。垃圾收集程序會自動從這些無效版本回收空間，以供未來操作使用。

當集合的索引因為頁面中累積無效或過時的索引項目或分段而變大時，就會發生索引膨脹。報告的百分比代表未來索引項目可以使用的索引空間量。此膨脹會耗用緩衝區快取和儲存體中的空間。如果您想要移除膨脹，則需要重建索引。

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

```
db.coll.aggregate({$indexStats:{}});
```
結果如下所示：  

```
{ 
    "name" : "_id_",
    "key" : { 
        "_id" : 1 
    },
    "host" : "devbox-test.localhost.a2z.com:27317",
    "size" : NumberLong(827392),
    "accesses" : {
        "ops" : NumberLong(40000),
        "docsRead" : NumberLong(46049),
        "since" : ISODate("2025-04-03T21:44:51.251Z") 
    },
    "cacheStats" : {
        "blksRead" : NumberLong(264),
        "blksHit" : NumberLong(140190),
        "hitRatio" : 99.8121
    }, 
    "unusedStorageSize" : {
        "unusedSizeBytes" : 409600,
        "unusedSizePercent" : 49.51
    }
}
```

您可以使用 `reIndex`命令重建索引，而不需要停機，這需要掃描整個集合。請參閱[使用 的索引維護 `reIndex`](managing-indexes.md#reIndex)。

# 對效能和資源使用率進行故障診斷
<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: {}
                  });
  ```

# Amazon DocumentDB 中的垃圾回收
<a name="garbage-collection"></a>

Amazon DocumentDB 實作多版本並行控制 (MVCC) 資料庫架構，為每個更新操作建立新的文件和索引項目版本。此架構提供啟用交易隔離，防止一個交易的變更出現在另一個交易中。

**Topics**
+ [了解 Amazon DocumentDB 中的垃圾回收](#understanding-garbage-collection)
+ [垃圾回收程序](#garbage-collection-process)
+ [儲存架構和擴充儲存](#storage-architecture)
+ [監控垃圾收集](#monitoring-garbage-collection)
+ [collStats 輸出範例](#example-collstats-output)
+ [常見問答集](#garbage-collection-faq)

## 了解 Amazon DocumentDB 中的垃圾回收
<a name="understanding-garbage-collection"></a>

垃圾回收 (GC) 是一種自動化背景程序，可在 Amazon DocumentDB 中維持最佳的系統效能和可用性。如同許多現代資料庫，Amazon DocumentDB 的 MVCC 架構會在每次更新時建立新的文件和索引版本。每個寫入操作都會從有限計數器使用唯一的 MVCC ID。這些 IDs會識別文件版本所屬的交易，以及文件版本是否已遞交或復原。隨著時間的推移，這些舊版本及其 MVCC IDs會累積，需要清除以防止效能降低。

### 垃圾回收的函數
<a name="w2aac49c15b7b5"></a>

垃圾收集器提供三個基本函數：
+ **回收儲存空間** — 它移除作用中查詢不再需要的過時文件和索引版本，為未來的寫入操作釋放空間。
+ **防止 MVCC ID 溢位** — 透過管理 MVCC ID 的有限計數器來防止 MVCC IDs 溢位。如果沒有此管理，計數器最終會達到其限制，強制資料庫進入暫時唯讀模式，直到 IDs回收為止。
+ **維持查詢效能** — 它透過消除可能累積和減慢查詢處理的無效文件版本，來維持最佳的查詢效能。

## 垃圾回收程序
<a name="garbage-collection-process"></a>

GC 程序會依集合操作，並且可以在不同的集合上同時執行多個程序。程序包含四個循序階段：

1. **識別** — 系統會識別作用中交易或查詢不再參考的文件和索引版本。

1. **記憶體載入** — 如果舊文件和索引項目尚未存在，則會載入記憶體。

1. **刪除** — 永久刪除過時的版本以回收儲存空間。

1. **MVCC ID 回收** — 系統會從已刪除的版本回收 MVCC IDs 以進行新操作。

當垃圾收集完成處理舊文件版本時，它會從系統中移除最舊的 MVCC IDs。此清除對於透過回收 MVCC ID 來防止 MVCC IDs 溢位至關重要，使其可用於整個叢集的新寫入操作。如果沒有此回收程序，系統最終會耗盡其有限的 MVCC ID 計數器，並進入唯讀狀態。

### 垃圾回收排程
<a name="w2aac49c15b9b9"></a>

垃圾回收會定期在背景中自動執行。時間和頻率會根據系統負載、可用資源、寫入磁碟區和 MVCC ID 耗用量層級動態調整。在高寫入活動期間，GC 程序會更頻繁地執行，以管理增加的文件版本數量。

## 儲存架構和擴充儲存
<a name="storage-architecture"></a>

Amazon DocumentDB 使用複雜的儲存架構，將文件儲存區分成兩個不同的區段：

### 基本儲存區段
<a name="w2aac49c15c11b5"></a>

基本儲存區段包含主要文件資料和中繼資料。此區段存放區：
+ 符合標準頁面大小 (8 KB) 的文件內容。
+ 文件中繼資料和結構資訊。
+ 主要索引及其項目。
+ 集合層級統計資料和組態。

### 擴充儲存區段
<a name="w2aac49c15c11b7"></a>

延伸的儲存區段使用專門的大型文件物件存放區，旨在處理超過標準儲存頁面大小的文件。此區段提供：
+ **高效率大型文件處理** — 大於基本儲存閾值的文件會自動移至擴充儲存區段。
+ **最佳化儲存配置** — 區段使用針對大型物件最佳化的不同儲存格式，減少分段並改善存取模式。
+ **獨立垃圾回收** — 延伸的儲存區段具有自己的垃圾回收程序，可以獨立於基本儲存清理執行。
+ **透明存取** — 應用程式無縫存取大型文件，而不需要知道哪些儲存區段包含資料。

延伸的儲存區段特別有益於：
+ 包含大型內嵌陣列之文件的集合。
+ 具有廣泛巢狀結構的文件。
+ 儲存二進位資料或大型文字欄位的集合。
+ 混合文件大小的應用程式，其中某些文件明顯超過平均大小。

## 監控垃圾收集
<a name="monitoring-garbage-collection"></a>

### 叢集層級指標
<a name="w2aac49c15c13b3"></a>

**`AvailableMVCCIds`**
+ **位置** — Amazon CloudWatch
+ **描述** — 顯示最大限制為 18 億的剩餘寫入操作數量的計數器。當此計數器達到零時，您的叢集會進入唯讀模式IDs直到 ID 回收和回收為止。計數器會隨著每次寫入操作而減少，並隨著垃圾回收回收舊的 MVCC IDs 而增加。
+ **建議** — 當值低於 13 億時設定警示。此提早警告可讓您採取稍後討論的建議步驟。

**`LongestActiveGCRuntime`**
+ **位置** — Amazon CloudWatch
+ **描述** — 最長作用中垃圾收集程序的持續時間，以秒為單位。每分鐘更新一次，並僅追蹤作用中的操作，不包括在一分鐘時段內完成的程序。
+ **建議** — 與`gcRuntimeStats`歷史資料進行比較，以識別異常的垃圾收集行為，例如在大量刪除期間延長執行時間。

### 集合層級指標
<a name="w2aac49c15c13b5"></a>

**`MVCCIDStats: MVCCIdScale`**
+ **位置** — 資料庫 collStats 命令
+ **描述** — 以 0 到 1 的規模測量 MVCC ID 存留期，其中 1 表示叢集進入唯讀狀態之前的最大存留期。將此指標與 一起`AvailableMVCCIds`用於識別包含正在使叢集老化之最舊 MVCC IDs集合。
+ **建議** — 將每個集合的值保持在 0.3 以下。

**`gcRuntimeStats`**
+ **位置** — 資料庫 collStats 命令
+ **描述** — 提供垃圾收集指標的兩個月歷史記錄，包括總執行次數、平均持續時間和最長持續時間。僅包含持續超過五分鐘的垃圾回收操作，以確保有意義的統計資料。

**重要**  
`gcRuntimeStats`、 `documentFragmentStats`和 將集合層級指標分解為 `storageSegmentBase`，`storageSegmentExtended`且僅適用於 Amazon DocumentDB 8.0。

**`storageSizeStats`**
+ **位置** — 資料庫 collStats 命令
+ **描述** — 提供不同儲存區段的儲存使用率詳細明細：
  + `storageSegmentBase` — 標準文件的基礎儲存區段所使用的儲存體
  + `storageSegmentExtended` — 擴充儲存區段用於大型文件的儲存體
+ **用量** — 協助識別具有大量大型文件儲存的集合，並了解儲存分佈模式。

**`unusedStorageSize`** （集合層級）
+ **位置** — 資料庫 collStats 命令
+ **描述** — 根據取樣的統計資料，估計集合中未使用的儲存空間。它包含已刪除文件和空白區段的空間。指標同時提供合併總計和每個區段明細：
  + 在所有儲存區段`unusedPercent`中結合 `unusedBytes`和
  + `storageSegmentBase` — 特別是在基本儲存區段中未使用的空間
  + `storageSegmentExtended` — 特別是在擴充儲存區段中未使用的空間

**`documentFragmentStats`**
+ **位置** — 資料庫 collStats 命令
+ **描述** — 提供有關集合中文件片段和無效資料的詳細資訊。文件片段代表資料庫引擎使用的內部儲存單位，而無效片段則表示無法再存取但尚未回收的資料。此指標包括：
  + `totalDocFragmentsCount` — 集合中的文件片段總數
  + `deadDocFragmentsCount` — 包含無效 （無法存取） 資料的片段數量
  + `deadDocFragmentsPercent` — 包含無效資料的片段百分比
  + `deadDocFragmentBytes` — 無效文件片段耗用的預估位元組數
  + `storageSegmentBase` 和 的每個區段明細 `storageSegmentExtended`
+ **用量** — 監控此指標以了解垃圾收集的有效性，並識別可能受益於維護操作的收集。高百分比的無效片段表示垃圾回收可能落後，或集合將受益於最佳化。

### 索引層級指標
<a name="w2aac49c15c13b7"></a>

**`unusedStorageSize`** （索引層級）
+ **Location** — 資料庫 indexStats 命令
+ **描述** — 根據取樣的統計資料，估計索引中未使用的儲存空間。它包含來自過時索引項目和空白區段的空間。
+ **建議** — 使用 `reIndex`命令來重建索引，無需停機時間並回收未使用的空間。如需詳細資訊，請參閱管理索引。

## collStats 輸出範例
<a name="example-collstats-output"></a>

下列範例顯示具有垃圾收集和儲存指標的典型`collStats`輸出：

```
{
    "ns" : "Mvcc_consumption_test_db.mvcc_test_collection",
    "MVCCIdStats" : {
        "MVCCIdScale" : 0.03
    },
    "gcRuntimeStats" : {
        "numRuns" : 1,
        "historicalAvgRuntime" : 3295,
        "historicalMaxRuntime" : 3295,
        "lastRuntime" : 3295,
        "lastRuntimeStart" : ISODate("2025-06-24T08:47:14Z")
    },
    "documentFragmentStats" : {
        "totalDocFragmentsCount" : 45000000,
        "deadDocFragmentsCount" : 2250000,
        "deadDocFragmentsPercent" : 5.0,
        "deadDocFragmentBytes" : 98304000,
        "storageSegmentBase" : {
            "totalDocFragmentsCount" : 30000000,
            "deadDocFragmentsCount" : 1500000,
            "deadDocFragmentsPercent" : 5.0,
            "deadDocFragmentBytes" : 65536000
        },
        "storageSegmentExtended" : {
            "totalDocFragmentsCount" : 15000000,
            "deadDocFragmentsCount" : 750000,
            "deadDocFragmentsPercent" : 5.0,
            "deadDocFragmentBytes" : 32768000
        }
    },
    "collScans" : 14,
    "count" : 30000000,
    "size" : 1320000000,
    "avgObjSize" : 44,
    "storageSize" : 6461497344,
    "storageSizeStats" : {
        "storageSegmentBase" : 4307664896,
        "storageSegmentExtended" : 2153832448
    },
    "capped" : false,
    "nindexes" : 2,
    "totalIndexSize" : 9649553408,
    "indexSizes" : {
        "_id_" : 1910661120,
        "c_1" : 7738892288
    },
    "unusedStorageSize" : {
        "unusedBytes" : 4201881600,
        "unusedPercent" : 65.05,
        "storageSegmentBase" : {
            "unusedBytes" : 2801254400,
            "unusedPercent" : 65.05
        },
        "storageSegmentExtended" : {
            "unusedBytes" : 1400627200,
            "unusedPercent" : 65.05
        }
    },
    "cacheStats" : {
        "collBlksHit" : 171659016,
        "collBlksRead" : 754061,
        "collHitRatio" : 99.5627,
        "idxBlksHit" : 692563636,
        "idxBlksRead" : 1177921,
        "idxHitRatio" : 99.8303
    },
    "idxScans" : 41823984,
    "opCounter" : {
        "numDocsIns" : 0,
        "numDocsUpd" : 20911992,
        "numDocsDel" : 0
    },
    "lastReset" : "2025-06-24 05:57:08.219711+00",
    "ok" : 1,
    "operationTime" : Timestamp(1750968826, 1)
}
```

## 常見問答集
<a name="garbage-collection-faq"></a>

### 如何識別垃圾回收是否無法有效運作？
<a name="w2aac49c15c17b3"></a>

監控這些警告訊號，指出垃圾回收效率不佳：
+ **過多的集合 Bloat** — 在大量寫入或大量刪除期間穩定增加`unusedStorageSize`指標，尤其是大型索引。
+ **高無效片段百分比** — `documentFragmentStats`持續顯示高`deadDocFragmentsPercent`值 （高於 10-15%)。
+ **查詢延遲降級** — 由於累積的無效文件而增加的查詢延遲。
+ **延長 GC 持續時間** — 垃圾回收操作耗時超過 中的歷史平均值`gcRuntimeStats`。
+ **提升 GC 處理** — 高`LongestActiveGCRuntime`表示垃圾收集器無法跟上系統需求。

### 垃圾回收是否會影響我的資料庫效能？
<a name="w2aac49c15c17b5"></a>

在正常情況下，垃圾回收對效能的影響最小。不過，當垃圾回收落後時，您可能會遇到：
+ 從累積的無效文件增加儲存成本。
+ 因索引項目過時而降低查詢效能。
+ 如果 MVCC IDs，則為暫時唯讀模式。
+ 密集收集執行期間較高的資源使用量，特別是在較小的執行個體上。
+ 降低大型文件擴充儲存區段操作的效率。

### 我可以手動觸發垃圾回收嗎？
<a name="w2aac49c15c17b7"></a>

否，Amazon DocumentDB 中的垃圾回收無法手動觸發。系統會自動管理垃圾回收，做為其內部維護操作的一部分。

### 我應該將哪些警示設定為操作最佳實務？
<a name="w2aac49c15c17b9"></a>

我們建議在叢集和集合層級設定監控，以確保 Amazon DocumentDB 系統的最佳效能。

對於叢集層級監控，請先為閾值為 13 億的`AvailableMVCCIds`指標建立 Amazon CloudWatch 警示。這可讓您有足夠的時間在指標達到零之前採取動作，此時您的叢集會進入唯讀模式。請記住，此指標可能會根據您的特定使用模式而波動，有些客戶會看到它低於 13 億，然後隨著垃圾回收完成其工作而復原超過 15 億。

透過 Amazon CloudWatch 監控`LongestActiveGCRuntime`指標也很重要。此指標與 `gcRuntimeStats`可協助您了解整個系統垃圾收集的效率。

對於集合層級監控，請專注於這些關鍵指標：
+ `MVCCIdScale` — 留意顯示 MVCC IDs 正在老化且可能需要注意的增加值。
+ `gcRuntimeStats` — 識別需要異常長時間或持續數天的垃圾回收程序。
+ `documentFragmentStats` — 監控`deadDocFragmentsPercent`值 - 持續高百分比 （超過 10-15%) 可能表示垃圾回收落後。
+ `storageSizeStats` 和 `unusedStorageSize` — 追蹤儲存使用率模式，並在任一儲存區段中識別具有顯著未使用空間的集合。

具有頻繁寫入操作的集合需要額外注意，因為它們為垃圾收集器產生更多工作。對於具有繁重寫入活動的集合，我們建議您更頻繁地檢查這些指標，以確保垃圾收集與您的工作負載保持一致。

請注意，這些監控建議做為起點。當您更熟悉系統的行為時，建議您調整這些閾值，以更符合您的特定使用模式和需求。

### 如果我的 `AvailableMVCCIds` 低於 13 億，該怎麼辦？
<a name="w2aac49c15c17c11"></a>

如果您的`AvailableMVCCIds`指標低於 13 億，建議您立即採取行動，以防止您的叢集進入唯讀模式。我們建議您先擴展執行個體大小，為垃圾收集器提供更多運算資源。這是我們的主要建議，因為它可讓您的應用程式繼續正常操作，同時為垃圾收集器提供追上所需的額外能力。

如果單獨擴展無法改善情況，建議您考慮減少寫入操作。使用 `MVCCIdScale` 指標來識別哪些特定集合包含需要注意的較舊 MVCC IDs。此外，監控 `documentFragmentStats` 以識別具有高無效片段百分比的集合，這些百分比可能會導致垃圾回收效率低下。

識別這些集合之後，您可能需要暫時減少這些集合的寫入操作，以允許垃圾收集追上進度。在復原期間，我們建議您密切監控 `AvailableMVCCIds` 指標，以確保您的動作具有所需的效果。一旦`AvailableMVCCIds`值回到 15 億或更高，您的叢集就會被視為運作狀態良好。

請記住，這些步驟是預防措施，可協助您的系統在達到嚴重狀態之前復原。看到指標降到 13 億以下之後，您採取動作的速度越快，就越有可能避免對寫入操作造成任何影響。