在 Azure Cosmos DB 中优化性能:最佳实践和技巧

當我們在使用資料庫時,優化對於應用程式的性能和效率至關重要。同樣地,在 Azure Cosmos DB 中,優化對於最大化效率、最小化成本以及確保應用程式有效擴展也至關重要。以下是一些最佳實踐以及代碼範例,以優化 Azure Cosmos DB 的性能。

1. 選擇正確的分區鍵

選擇適當的分區鍵對於像 Cosmos DB 這樣的分散式資料庫至關重要。一個好的分區鍵確保數據在分區之間均勻分佈,減少熱點 並提升性能。

在 Azure Cosmos DB 中,選擇分區鍵雖然簡單,但在設計階段非常重要。一旦 我們 選擇了 分區鍵,就無法在原地更改它。

最佳實踐

  • 選擇具有高基數(許多唯一值)的分區鍵。
  • 確保它均勻地分配讀取和寫入。
  • 將相關數據放在一起,以最小化跨分區查詢。

範例:創建具有最佳分區鍵的容器

C#

 

var database = await cosmosClient.CreateDatabaseIfNotExistsAsync("YourDatabase");
var containerProperties = new ContainerProperties
{
    Id = "myContainer",
    PartitionKeyPath = "/customerId"  // Partition key selected to ensure balanced distribution
}; 

// 使用 400 RU/s 的預配置吞吐量創建容器
var container = await database.CreateContainerIfNotExistsAsync(containerProperties, throughput: 400);

2. 正確地使用索引

在 Azure Cosmos DB 中,默認情況下對所有屬性應用索引,這可能是有益的,但也可能導致增加存儲和 RU/s 成本。為了增強查詢性能並最大程度地減少費用,請考慮自定義索引策略。 Cosmos DB 支持三種類型的索引:範圍索引、空間索引和複合索引。 明智地選擇適當的類型。

最佳實踐

  • 排除不必要的字段進行索引。
  • 對於多字段查詢,使用複合索引。

示例:自定義索引策略

C#

 

{
    "indexingPolicy": {
        "automatic": true,
        "indexingMode": "consistent",  // Can use 'none' or 'lazy' to reduce write costs
        "includedPaths": [
            {
                "path": "/orderDate/?",  // Only index specific fields like orderDate
                "indexes": [
                    {
                        "kind": "Range",
                        "dataType": "Number"
                    }
                ]
            }
        ],
        "excludedPaths": [
            {
                "path": "/largeDataField/*"  // Exclude large fields not used in queries
            }
        ]
    }
}

示例:添加複合索引以進行優化查詢

C#

 

{
    "indexingPolicy": {
        "compositeIndexes": [
            [
                { "path": "/lastName", "order": "ascending" },
                { "path": "/firstName", "order": "ascending" }
            ]
        ]
    }
}

您可以在此處閱讀有關索引類型的更多信息

3. 優化查詢

在 Azure Cosmos DB 中,高效的查詢對於最小化請求單位(RU/s)和提高性能至關重要。 RU/s 成本取決於查詢的複雜性和大小。

使用批量執行程序可以進一步降低成本,減少每個操作消耗的 RU 數量。這種優化有助於有效管理 RU 使用量,降低您的整體 Cosmos DB 費用。

最佳實踐

  • 使用 SELECT 查詢在有限的數量中,僅檢索必要的屬性。
  • 通過在查詢中提供分區鍵來避免跨分區查詢。
  • 在索引字段上使用過濾器以降低查詢成本。

示例:獲取客戶記錄

C#

 

var query = new QueryDefinition("SELECT c.firstName, c.lastName FROM Customers c WHERE c.customerId = @customerId")
    .WithParameter("@customerId", "12345");

var iterator = container.GetItemQueryIterator<Customer>(query, requestOptions: new QueryRequestOptions
{
    PartitionKey = new PartitionKey("12345")  // Provide partition key to avoid cross-partition query
});

while (iterator.HasMoreResults)
{
    var response = await iterator.ReadNextAsync();
    foreach (var customer in response)
    {
        Console.WriteLine($"{customer.firstName} {customer.lastName}");
    }
}

4. 一致性等級調整

一致性等級定義了旨在滿足速度相關保證的特定操作模式。 有五種一致性等級(強一致性、有限陳舊、一致性會話、一致前綴和最終一致性)可用於Cosmos DB。每種一致性等級都會影響延遲、可用性和吞吐量。

最佳實踐

  • 在大多數場景中使用會話一致性來平衡性能和數據一致性。
  • 強一致性保證數據一致性,但會增加 RU/s 和延遲。

示例:設置一致性等級

C#

 

var cosmosClient = new CosmosClient(
    "",
    "",
    new CosmosClientOptions
    {
        // 將一致性設置為「會話」以獲得平衡性能
		ConsistencyLevel = ConsistencyLevel.Session      
});

在這裡閱讀有關一致性等級的更多資訊這裡

5. 明智地使用預配置吞吐量 (RU/s) 和自動擴展

預配置吞吐量是實現 Azure Cosmos DB 成本效益和最佳性能的關鍵因素。該服務允許您以兩種方式配置吞吐量:

  • 固定 RU/s一個預定義的、恆定的每秒請求單位 (RU/s) 水平,適合性能需求穩定的工作負載。
  • 自動擴展一個動態選項,根據工作負載變化自動調整吞吐量,在低活動期間提供可擴展性,同時避免過度配置。

選擇合適的吞吐量模型有助於有效平衡性能需求與成本管理。

最佳實踐

  • 對於可預測的工作負載,手動配置吞吐量。
  • 對於不可預測或突發的工作負載,使用自動擴展。

範例:使用 自動擴展配置吞吐量

C#

 

var throughputProperties = ThroughputProperties.CreateAutoscaleThroughput(maxThroughput: 4000);  // Autoscale up to 4000 RU/s 
var container = await database.CreateContainerIfNotExistsAsync(new ContainerProperties
{
	Id = "autoscaleContainer",
	PartitionKeyPath = "/userId"
}, throughputProperties);

範例:為穩定工作負載手動設置固定 RU/s 

C#

 

var container = await database.CreateContainerIfNotExistsAsync(new ContainerProperties
{
    Id = "manualThroughputContainer",
    PartitionKeyPath = "/departmentId"
}, throughput: 1000);  // Fixed 1000 RU/s

6. 利用變更訂閱進行高效的實時處理

變更訂閱允許通過自動捕獲數據庫中的變更來實現實時的事件驅動處理,消除了輪詢的需要。這減少了查詢開銷並提高了效率。

最佳實踐

  • 在需要處理實時數據變更的場景中使用變更訂閱(例如,實時分析、通知、警報)。

範例:從變更訂閱中讀取

C#

 

var iterator = container.GetChangeFeedIterator(
ChangeFeedStartFrom.Beginning(),
ChangeFeedMode.Incremental);
while (iterator.HasMoreResults)
{
    var changes = await iterator.ReadNextAsync();
    foreach (var change in changes)
    {
        Console.WriteLine($"Detected change: {change.Id}");
        // 處理變更(例如,觸發事件,更新快取)
    }
}

7. 利用生存時間(TTL)進行自動數據過期

如果您擁有僅在有限時間內相關的數據,例如日誌或會話數據,則在 Azure Cosmos DB 中啟用生存時間(TTL)可以幫助管理存儲成本。TTL會在指定的保留期後自動刪除過期數據,消除了手動數據清理的需要。這種方法不僅減少了存儲數據的數量,還通過刪除過時或不必要的信息來確保您的數據庫在成本效率方面得到最佳化。

最佳實踐

  • 為應該自動過期的容器設置 TTL,以減少存儲成本。

範例:為過期數據設置生存時間(TTL)

C#

 

{
    "id": "sessionDataContainer",
    "partitionKey": { "paths": ["/sessionId"] },
    "defaultTtl": 3600  // 1 hour (3600 seconds)
}

在 Cosmos DB 中,可以設定的最大存活時間 (TTL) 值為 365 天(1 年)。 這意味著資料在創建或最後修改後的一年內到期後,可以自動刪除,具體取決於您如何配置 TTL。

8. 避免跨分區查詢

跨分區查詢可能會顯著增加 RU/s 和延遲。為了避免這種情況:

最佳實踐

  • 始終在查詢中包含分區鍵。
  • 設計您的分區策略以最小化跨分區訪問。

示例:使用分區鍵查詢以避免跨分區查詢

C#

 

var query = new QueryDefinition("SELECT * FROM Orders o WHERE o.customerId = @customerId")
    .WithParameter("@customerId", "12345"); 

var resultSetIterator = container.GetItemQueryIterator<Order>(query, requestOptions: new QueryRequestOptions
{
    PartitionKey = new PartitionKey("12345")
});

while (resultSetIterator.HasMoreResults)
{
    var response = await resultSetIterator.ReadNextAsync();
    foreach (var order in response)
    {
        Console.WriteLine($"Order ID: {order.Id}");
    }
}

結論

這些提示在開發過程中非常有效。通過實施有效的分區策略、自定義索引政策、優化查詢、調整一致性級別以及選擇適當的吞吐量配置模型,您可以大大提高 Azure Cosmos DB 部署的性能和效率。這些優化不僅提升了可擴展性,還有助於管理成本,同時提供高性能的資料庫體驗。

Source:
https://dzone.com/articles/optimizing-performance-in-azure-cosmos-db