Azure Cosmos DB × .NET のデータモデリング — RU を最小化する設計原則
Database

Azure Cosmos DB × .NET のデータモデリング — RU を最小化する設計原則

公開: 更新: 約2分で読めます

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
Cosmos DB の操作種別ごとの RU 消費比較(Point Read / インデックスクエリ / クロスパーティションクエリ / 集計スキャン)
1 リクエストあたりの RU は操作設計で 2 桁以上変わる。Point Read 優先の設計が RU 予算を守る近道。

原則 5: インデックスポリシーを明示する

Cosmos DB はデフォルトで全フィールドを自動インデックスします。書き込み RU を抑えたければ、検索に使わないパスを除外する設定が有効です。

計測と運用

  • SDK の RequestCharge を常時ロギングし、ホットクエリを可視化。
  • Azure Monitor で「分間合計 RU」を 80% 閾値でアラート化。
  • 1 つのクエリが 50 RU を超えたら設計見直しのサイン。

まとめ

Cosmos DB はスケーラビリティが魅力ですが、設計を誤ると請求書でも伸びます。.NET SDK の機能を活用し、最初から RU を意識した設計を心がけることが、長期的なコスト削減につながります。