データベースを扱う際、最適化はアプリケーションのパフォーマンスと効率にとって極めて重要です。同様に、Azure Cosmos DBでも、最適化は効率を最大化し、コストを最小限に抑え、アプリケーションのスケーラビリティを確保するために重要です。以下は、Azure Cosmos DBでパフォーマンスを最適化するためのベストプラクティスとコーディング例です。
1. 適切なパーティションキーの選択
適切なパーティションキーの選択は、Cosmos DBなどの分散データベースにとって重要です。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. 正しい Uインデックスの使用
Azure Cosmos DBでは、デフォルトで全てのプロパティにインデックスが適用されます。これは有益な場合もありますが、ストレージとRU/sコストが増加する可能性があります。クエリのパフォーマンスを向上させ、コストを最小限に抑えるために、インデックスポリシーをカスタマイズすることを検討してください。 Cosmos DBは、範囲インデックス、空間インデックス、複合インデックスの3種類のインデックスをサポートしています。 適切なタイプを賢く使用してください。
ベストプラクティス
- インデックスから不要なフィールドを除外してください。
- 複数フィールドのクエリには複合インデックスを使用してください。
例: カスタムインデックスポリシー
{
"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コストは、クエリの複雑さとサイズに依存します。
バルクエグゼキュータを利用することで、操作ごとの消費RUを減少させ、コストをさらに削減できます。この最適化は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. 整合性レベルの調整
整合性レベルは、速度関連の保証を満たすために設計された特定の操作モードを定義します。 5つの整合性レベル(Strong、Bounded Staleness、Session、Consistent Prefix、Eventual)がCosmos DBで利用可能です。 各整合性レベルは、レイテンシ、可用性、スループットに影響を与えます。
ベストプラクティス
- ほとんどのシナリオでセッション整合性を使用して、パフォーマンスとデータの整合性をバランスさせます。
- Strong整合性はデータの整合性を保証しますが、RU/sおよびレイテンシが増加します。
例: 整合性レベルの設定
var cosmosClient = new CosmosClient(
"",
"",
new CosmosClientOptions
{
// パフォーマンスをバランスさせるために整合性を「セッション」に設定
ConsistencyLevel = ConsistencyLevel.Session
});
整合性レベルについて詳しくはこちらをご覧ください。
5. プロビジョニングスループット (RU/s) とオートスケールを賢く利用する
スループットのプロビジョニングは、Azure Cosmos DBにおいてコスト効率と最適なパフォーマンスを達成するための重要な要素です。このサービスでは、スループットを2つの方法で設定できます:
- 固定 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. 変更フィードを活用して効率的なリアルタイム処理を行う
変更フィードは、データベースの変更を自動的にキャプチャしてポーリングの必要性を排除し、リアルタイムでイベント駆動型の処理を可能にします。これにより、クエリのオーバーヘッドが減少し、効率が向上します。
ベストプラクティス
- リアルタイムのデータ変更が処理される必要があるシナリオ(例:リアルタイム分析、通知、アラート)には変更フィードを使用します。
例:変更フィードからの読み取り
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を設定してストレージコストを削減します。
例:期限切れデータのためのTime-to-Live(TTL)の設定
{
"id": "sessionDataContainer",
"partitionKey": { "paths": ["/sessionId"] },
"defaultTtl": 3600 // 1 hour (3600 seconds)
}
Cosmos DBでは、設定できる最大Time-to-Live(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