Cosmos DB のコスト構造
Azure Cosmos DB の料金はRU(Request Unit)の消費量に直結します。RU はクエリの重さで決まるので、データモデリングを間違えると従量課金が跳ね上がります。本記事では .NET アプリで Cosmos DB を扱う際の設計原則を整理します。
原則 1: パーティションキーの選定がすべて
パーティションキーの選定は、Cosmos DB 設計において最も重要で後から変更しにくい決定です。
- カーディナリティが高い(値の種類が多い)ことが必須。
- クエリの WHERE 句に頻出するフィールドを選ぶ。
- 1 パーティション 20GB / 10,000 RU/s の上限を超えないサイズになるよう見積もる。
原則 2: 集計クエリは事前計算する
SELECT COUNT(c) FROM c WHERE ... のようなクエリは全ドキュメントスキャンに近く RU を大量に消費します。Change Feed で集計結果を別コンテナに書き込むパターンが定石です。
var processor = cosmosClient
.GetContainer("db", "orders")
.GetChangeFeedProcessorBuilder<Order>(
"aggregator",
async (changes, ct) =>
{
foreach (var o in changes) await UpdateDailyTotal(o);
})
.WithInstanceName("agg-1")
.WithLeaseContainer(leaseContainer)
.Build();
await processor.StartAsync();
原則 3: 埋め込み vs 参照のバランス
リレーショナル脳で設計すると過度に正規化してしまいがちですが、Cosmos DB では一緒に読むデータは一緒に保存するのが原則です。
- 1 対多で「多」が 100 件以下、変更頻度が低い → 埋め込み
- 多対多、件数不定、独立して変更される → 参照
原則 4: Point Read を最優先にする
ReadItemAsync<T>(id, partitionKey) は Cosmos DB で最も RU が安い操作(1KB のドキュメントで 1 RU)。ID とパーティションキーの組み合わせで直接取れる設計にできれば、それが最速・最安です。
var response = await container.ReadItemAsync<Order>(
id: orderId, partitionKey: new PartitionKey(tenantId));
var order = response.Resource;
// 消費 RU: response.RequestCharge
原則 5: インデックスポリシーを明示する
Cosmos DB はデフォルトで全フィールドを自動インデックスします。書き込み RU を抑えたければ、検索に使わないパスを除外する設定が有効です。
計測と運用
- SDK の
RequestChargeを常時ロギングし、ホットクエリを可視化。 - Azure Monitor で「分間合計 RU」を 80% 閾値でアラート化。
- 1 つのクエリが 50 RU を超えたら設計見直しのサイン。
まとめ
Cosmos DB はスケーラビリティが魅力ですが、設計を誤ると請求書でも伸びます。.NET SDK の機能を活用し、最初から RU を意識した設計を心がけることが、長期的なコスト削減につながります。
