在使用数据库时,优化对于应用程序性能和效率至关重要。同样,在 Azure Cosmos DB 中,优化对于最大化效率、最小化成本和确保应用程序有效扩展也至关重要。以下是一些最佳实践以及编码示例,以优化 Azure Cosmos DB 的性能。
1. 选择合适的分区键
为像 Cosmos DB 这样的分布式数据库选择合适的分区键至关重要。良好的分区键确保数据在分区中均匀分布,减少热点,并提高性能。
在 Azure Cosmos DB 的设计阶段,选择分区键虽然简单,但非常重要。一旦 我们 选择了 分区键,便无法在原地更改它。
最佳实践
- 选择具有高基数(许多唯一值)的分区键。
- 确保它均匀分布读取和写入。
- 将相关数据放在一起,以最小化跨分区查询。
示例:创建具有最佳分区键的容器
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支持三种类型的索引:范围索引、空间索引和复合索引。 明智地使用适当的类型。
最佳实践
- 排除不必要的字段进行索引。
- 对于多字段查询,请使用复合索引。
示例:自定义索引策略
{
"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
}
]
}
}
示例:添加复合索引以优化查询
{
"indexingPolicy": {
"compositeIndexes": [
[
{ "path": "/lastName", "order": "ascending" },
{ "path": "/firstName", "order": "ascending" }
]
]
}
}
您可以在此处阅读更多关于索引类型的信息。
3. 优化查询
在Azure Cosmos DB中,高效的查询对于最小化请求单位(RU/s)和提高性能至关重要。RU/s成本取决于查询的复杂性和大小。
利用批量执行器可以进一步降低成本,减少每次操作消耗的RUs。这种优化有助于有效管理RU使用量,降低您的整体Cosmos DB开支。
最佳实践
- 使用
SELECT
查询时应限制查询量,仅检索必要的属性。 - 通过在查询中提供分区键,避免跨分区查询。
- 在索引字段上使用过滤器以降低查询成本。
示例:获取客户记录
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中提供了五种一致性级别(Strong、Bounded Staleness、Session、Consistent Prefix和Eventual)。每个一致性级别都会影响延迟、可用性和吞吐量。
最佳实践
- 大多数情况下使用会话一致性以平衡性能和数据一致性。
- 强一致性保证数据一致性但会增加 RU/s 和延迟。
示例:设置一致性级别
var cosmosClient = new CosmosClient(
"",
"",
new CosmosClientOptions
{
// 将一致性设置为“会话”以获得平衡的性能
ConsistencyLevel = ConsistencyLevel.Session
});
了解更多关于一致性级别的信息在此处。
5. 明智地使用预配吞吐量(RU/s)和自动缩放
在 Azure Cosmos DB 中,预配吞吐量是实现成本效益和最佳性能的关键因素。该服务允许您以两种方式配置吞吐量:
- 固定 RU/s: 预先定义的每秒请求单位(RU/s)的恒定级别,适用于具有一致性性能需求的工作负载。
- 自动缩放: 一种动态选项,根据工作负载的波动自动调整吞吐量,提供可伸缩性,同时避免在低活动期间过度预配。
选择适当的吞吐量模型有助于有效地平衡性能需求和成本管理。
最佳实践
- 对于可预测的工作负载,手动预配吞吐量。
- 对于不可预测或突发的工作负载,使用自动缩放。
示例:使用自动缩放预配吞吐量
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
var container = await database.CreateContainerIfNotExistsAsync(new ContainerProperties
{
Id = "manualThroughputContainer",
PartitionKeyPath = "/departmentId"
}, throughput: 1000); // Fixed 1000 RU/s
6. 利用变更 Feed 实现高效的实时处理
变更订阅通过自动捕获数据库中的变更,允许实时事件驱动处理,消除了轮询的需要。这减少了查询开销并提高了效率。
最佳实践
- 在需要处理实时数据更改的场景中使用变更订阅(例如,实时分析、通知、警报)。
示例:读取变更订阅
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)
{
"id": "sessionDataContainer",
"partitionKey": { "paths": ["/sessionId"] },
"defaultTtl": 3600 // 1 hour (3600 seconds)
}
在 Cosmos DB 中,可以设置的最大生存时间(TTL)值为 365 天(1 年)。 这意味着数据在创建或最后修改后的 1 年内到期后可以被自动删除,具体取决于您如何配置 TTL。
8. 避免跨分区查询
跨分区查询会显著增加 RU/s 和延迟。为了避免这种情况:
最佳实践
- 在查询中始终包含分区键。
- 设计您的分区策略以最小化跨分区访问。
示例:使用分区键查询以避免跨分区查询
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