

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

# 具有 3 個以上屬性的複合索引
<a name="anti-pattern-compound-index"></a>

## 概觀
<a name="compound-index-overview"></a>

複合或複合索引會維護單一索引結構中多個欄位的參考。這些索引會針對同時篩選多個欄位或結合篩選與排序操作的查詢最佳化效能。它們也適用於最左邊索引欄位上的單一條件查詢。資料庫會利用這些索引項目，有效率地尋找相符的文件，而無需執行完整的集合掃描。

Amazon DocumentDB 可以使用複合索引來支援查詢，其中包含索引欄位的任何主要子集，這個概念稱為索引字首。例如，如果您在 上有複合索引`{state: 1, city: 1, zipcode: 1}`，Amazon DocumentDB 可以有效率地處理使用欄位 'state' 單獨、欄位 'state' 和 'city' 一起，或所有三個欄位 'state'、'city' 和 'zipcode' 的查詢。不過，查詢必須使用從左到右的欄位，而不會略過其中的任何欄位。這表示僅使用欄位 'city' 或 'zipcode' 或組合的查詢，例如 'state' 和 'zipcode' （略過 'city')，無法完全利用索引。

在大多數真實世界案例中，具有三個或更少屬性的複合索引通常會達到最佳效能和資源效率。雖然複合索引中有超過 3 個屬性是可行的，但通常會導致資源消耗增加，超過優點。

## 對叢集的影響
<a name="compound-index-impact"></a>

雖然想要建立涵蓋查詢中所有條件的索引，以達到最大理論效能，但大多數資料篩選是透過複合索引中的前 1-3 個屬性進行。超過此閾值的其他欄位主要有助於索引大小，而不是有意義的查詢最佳化。

**儲存體和 I/O 額外負荷**：具有許多屬性的複合索引會耗用比較簡單替代方案更多的儲存空間。大小與索引的屬性數量以及索引值本身的大小成正比。

**記憶體佔用**空間：具有許多屬性的複合索引的大型儲存佔用空間會在記憶體中建立對應的佔用空間，讓您的工作集變大，並從緩衝集區取代其他經常存取的資料。

**寫入操作**：每個影響多個索引欄位的文件修改都需要更新整個複合索引項目，乘以完成寫入操作所需的工作。

## 如何識別
<a name="compound-index-identify"></a>

首先檢閱集合中的所有索引，以識別具有三個以上屬性的複合索引：

```
// List all indexes for the collection
db.collection.getIndexes()

// Look for indexes with 3+ fields like:

// { "userId": 1, "status": 1, "category": 1, "priority": 1, "region": 1 }
// { "orderId": 1, "customerId": 1, "productId": 1, "timestamp": 1, "warehouse": 1 }
```

## 修補
<a name="compound-index-remediation"></a>

如果使用具有三個以上屬性的複合索引，請識別使用它的查詢，並尋找最佳化機會。請考慮以包含三個或更少屬性的更有效率索引取代這些索引。實作新索引後，移除包含三個以上屬性的舊索引。

**注意**  
在捨棄任何索引之前，請務必與利益相關者協調並驗證效能影響。

建立複合索引時，請遵循等式、排序、範圍 (ESR) 規則。

**等式排序範圍 (ESR) 規則**：此排序會先以等式條件篩選資料集，然後在減少的集合上套用排序操作，最後在最小的可能子集上執行範圍掃描，藉此最大化索引效率
+ 將欄位排序為等式 （完全相符），
+ 排序 （排序）、
+ 範圍 (＞、＜、$in)。

```
// Query pattern
db.orders.find({ 
  userId: "user123",                    // Equality
  price: { $gte: 50, $lte: 200 }      // Range
}).sort({ createdAt: -1 })             // Sort

// Optimal index following ESR rule
db.orders.createIndex({ userId: 1, createdAt: -1, price: 1 })
//                      Equality   Sort         Range
```