Azure Cosmos DB でのパーティション分割と水平スケーリング

適用対象: SQL API Cassandra API Gremlin API Table API MongoDB 用 Azure Cosmos DB API

Azure Cosmos DB では、パーティション分割を使用して、データベースの個別のコンテナーをスケーリングし、アプリケーションのパフォーマンスのニーズを満たします。 パーティション分割では、コンテナー内の項目が、"論理パーティション" と呼ばれる特定のサブセットに分割されます。 論理パーティションは、コンテナー内の各項目に関連付けられている "パーティション キー" の値に基づいて形成されます。 1 つの論理パーティション内のすべての項目で、パーティション キーの値は同じです。

たとえば、あるコンテナーに項目が保持されているとします。 各項目の UserID プロパティには一意の値があります。 UserID がそのコンテナー内の項目のパーティション キーであり、1,000 個の一意の UserID 値がある場合、1,000 個の論理パーティションがそのコンテナー内に作成されます。

項目の論理パーティションを決めるパーティション キーに加えて、コンテナー内の各項目には "項目 ID" (論理パーティション内で一意) があります。 パーティション キーと 項目 ID を組み合わせて、項目の インデックス が作成されます。インデックスによって、項目が一意に識別されます。 パーティション キーを選択することは、アプリケーションのパフォーマンスに影響する重要な決定事項です。

この記事では、論理パーティションと物理パーティションの関係について説明します。 さらに、パーティション分割のベスト プラクティスと、Azure Cosmos DB での水平方向のスケーリングのしくみについて詳しく説明します。 これらの内部的な詳細について、ここでは Azure Cosmos DB のしくみを明確にすることを目的に説明していますが、パーティション キーを選択するために理解しておく必要はありません。

論理パーティション

論理パーティションは、同じパーティション キーを持つ一連のアイテムで構成されます。 たとえば、食物の栄養に関するデータが含まれているコンテナーでは、すべてのアイテムに foodGroup プロパティが含まれています。 このコンテナーのパーティション キーとして foodGroup プロパティを使用できます。 Beef ProductsBaked ProductsSausages and Luncheon Meats など、foodGroup に特定の値を持つアイテムのグループが、個別の論理パーティションを形成します。

論理パーティションでは、データベース トランザクションのスコープも定義します。 論理パーティション内のアイテムは、スナップショット分離が指定されたトランザクションを使用して更新することができます。 コンテナーに新しい項目が追加されると、新しい論理パーティションがシステムによって透過的に作成されます。 基になるデータを削除するときに、論理パーティションの削除について心配する必要はありません。

コンテナー内の論理パーティションの数に制限はありません。 各論理パーティションには、最大 20 GB のデータを格納できます。 適切なパーティション キーを選択すると、可能性がある多様な値を格納できます。 たとえば、すべてのアイテムに foodGroup プロパティが含まれているコンテナーでは、Beef Products 論理パーティション内のデータを最大 20 GB まで拡張できます。 可能性がある多様な値を格納できるパーティション キーを選択することで、コンテナーを確実にスケーリングできます。

物理パーティション

コンテナーは、物理パーティション間でデータとスループットを分散することでスケーリングされます。 内部的には、1 つまたは複数の論理パーティションが単一の物理パーティションにマップされます。 小さなコンテナーには通常、多くの論理パーティションがありますが、必要なのは 1 つの物理パーティションのみです。 論理パーティションとは異なり、物理パーティションはシステムの内部実装であり、完全に Azure Cosmos DB によって管理されます。

コンテナー内の物理パーティションの数は、以下によって決まります。

  • プロビジョニングされたスループットの数 (個々の物理パーティションからは、1 秒あたり最大 10,000 の要求ユニットのスループットを提供できます)。 物理パーティションに 10,000 RU/秒の制限がある場合、論理パーティションにも 10,000 RU/秒の制限があることを意味します。各論理パーティションは 1 つの物理パーティションにのみマップされるためです。

  • データ ストレージの合計 (個々の物理パーティションには、最大 50 GB のデータを格納できます)。

注意

物理パーティションはシステムの内部実装であり、完全に Azure Cosmos DB によって管理されます。 物理パーティションは制御できないため、ソリューションを開発するときは物理パーティションには重点を置かないでください。 代わりに、パーティション キーに重点を置いてください。 論理パーティション間でスループットの消費が均等に分散されるパーティション キーを選択すると、物理パーティション間でのスループットが確実に均等に消費されます。

コンテナー内の物理パーティションの合計数に制限はありません。 プロビジョニングされたスループットまたはデータ サイズが増加すると、Azure Cosmos DB によって既存のパーティションが分割され、新しい物理パーティションが自動的に作成されます。 物理パーティションの分割がアプリケーションの可用性に影響を与えることはありません。 物理パーティションが分割された後も、単一の論理パーティション内のすべてのデータは同じ物理パーティションに格納されます。 物理パーティションの分割では、物理パーティションに対する論理パーティションの新しいマッピングが作成されるだけです。

コンテナーに対してプロビジョニングされたスループットは、物理パーティション間で均等に分割されます。 要求を均等に分散しないようにパーティション キーを設計すると、"ホット" になるパーティションの小さなサブセットに送信される要求の数が過多となる可能性があります。 ホット パーティションは、プロビジョニングされたスループットの使用効率を低下させるため、レート制限が発生し、コストが高くなる場合があります。

コンテナーの物理パーティションは、Azure portal の [メトリック] ブレード[ストレージ] セクションで確認できます。

物理パーティションの数の表示

上のスクリーンショットでは、コンテナーに /foodGroup がパーティション キーとして存在しています。 グラフ内の 3 本のバーはそれぞれ、物理パーティションを表しています。 この図では、パーティション キー範囲 は物理パーティションと同じです。 選択されている物理パーティションには、上位 3 つの最も大きいサイズの論理パーティション (Beef ProductsVegetable and Vegetable ProductsSoups, Sauces, and Gravies) が含まれています。

スループットを 1 秒あたり 18,000 の要求ユニット (RU/秒) でプロビジョニングした場合、3 つの物理パーティションではそれぞれ、プロビジョニングされたスループットの合計の 3 分の 1 を利用できます。 選択されている物理パーティション内では、論理パーティション キー (Beef ProductsVegetable and Vegetable Products、および Soups, Sauces, and Gravies) は、物理パーティションにプロビジョニングされた 6,000 RU/秒を共同で利用できます。 プロビジョニングされたスループットはコンテナーの物理パーティション全体に均等に分割されるため、適切な論理パーティション キーの選択によって、スループットの消費が均等に分散されるパーティション キーを選択することが重要です。

論理パーティションの管理

Azure Cosmos DB では、論理パーティションの物理パーティションへの配置が透過的かつ自動的に管理され、コンテナーのスケーラビリティとパフォーマンスのニーズが効率的に満たされます。 アプリケーションのスループットとストレージの要件が上がると、Azure Cosmos DB は論理パーティションを移動し、より多くの物理パーティションに負荷を自動的に分散します。 物理パーティションの詳細を参照できます。

Azure Cosmos DB は、ハッシュベースのパーティション分割を使用して、論理パーティションを物理パーティションに分散します。 Azure Cosmos DB では、項目のパーティション キー値をハッシュします。 ハッシュの結果で、物理パーティションが決定します。 次に、Azure Cosmos DB が物理パーティションに対し、パーティション キー ハッシュのキー空間を均等に割り当てます。

ストアド プロシージャまたはトリガー内のトランザクションは、1 つの論理パーティション内の項目に対してのみ使用できます。

レプリカ セット

各物理パーティションは、一連のレプリカで構成されます ("レプリカ セット" とも呼ばれます)。 各レプリカ セットによって、データベース エンジンのインスタンスがホストされます。 レプリカ セットにより、物理パーティション内に格納されたデータの耐久性、高可用性、一貫性が確保されます。 物理パーティションを構成する各レプリカは、そのパーティションのストレージ クォータを継承します。 物理パーティションのすべてのレプリカは、物理パーティションに割り当てられたスループットを一元的にサポートします。 レプリカ セットは Azure Cosmos DB によって自動的に管理されます。

小さなコンテナーは通常、1 つの物理パーティションのみを必要としますが、少なくとも 4 つのレプリカが保持されます。

次の図は、グローバルに分散されている物理パーティションに論理パーティションがどのようにマップされているかを示しています。

Azure Cosmos DB パーティション分割を示す図

パーティション キーを使用する場合

パーティション キーには、パーティション キーのパスパーティション キーの値 の 2 つのコンポーネントがあります。 例として、項目 { "userId" :"Andrew", "worksFor":"Microsoft" } について考えてみます。パーティション キーとして "userId" を選択した場合、パーティション キーの 2 つのコンポーネントは次のようになります。

  • パーティション キーのパス (例: "/userId")。 パーティション キーのパスには、英数字とアンダースコア (_) 文字を使用できます。 また、標準パス表記 (/) を使用して、入れ子になったオブジェクトを使用することもできます。

  • パーティション キーの値 (例:"Andrew")。 パーティション キーの値には、文字列型または数値型を使用できます。

パーティション キーのスループット、ストレージ、および長さの制限については、記事「Azure Cosmos DB サービスのクォータ」を参照してください。

パーティション キーの選択はシンプルですが、Azure Cosmos DB での設計上の重要な選択です。 パーティション キーを選択した後は、その場で変更することはできません。 パーティション キーを変更する必要がある場合は、新しい必要なパーティション キーを使用して、新しいコンテナーにデータを移動する必要があります。

すべての コンテナーで、パーティション キーが次のようになっている必要があります。

  • 値が変更されないプロパティであること。 プロパティがパーティション キーの場合、そのプロパティの値を更新することはできません。

  • 高いカーディナリティがあること。 言い換えると、プロパティには、有効な値が広範囲に及ぶことが必要です。

  • 要求ユニット (RU) の消費量とデータ ストレージをすべての論理パーティションに均等に分散すること。 これにより、物理パーティション全体でも RU の消費とストレージの分散が保証されます。

Azure Cosmos DB で複数項目の ACID トランザクションが必要な場合は、ストアド プロシージャまたはトリガーを使用する必要があります。 すべての JavaScript ベースのストアド プロシージャとトリガーのスコープは、1 つの論理パーティションに限定されます。

読み取り負荷の高いコンテナーのパーティション キー

ほとんどのコンテナーでは、パーティション キーを選択するときに考慮する必要があるのは、上記の条件だけです。 ただし、大規模な読み取り負荷の高いコンテナーの場合は、クエリでフィルターとして頻繁に表示されるパーティション キーを選択することができます。 フィルターの述語にパーティション キーを含めることで、クエリ呼び出しを関係する物理パーティションにだけ効率的にルーティングできます。

ワークロードの要求のほとんどがクエリで、ほとんどのクエリが同じプロパティに対する等値フィルターを適用している場合、このプロパティが適切なパーティション キーの選択になりえます。 たとえば、UserID に対してフィルター処理を行うクエリを頻繁に実行する場合、パーティション キーとして UserID を選択するとクロスパーティション クエリの数が減少します。

ただし、コンテナーが小さい場合は、恐らくクロスパーティション クエリのパフォーマンスへの影響について心配するような量の物理パーティションがありません。 Azure Cosmos DB 内の小さなコンテナーのほとんどは、1 つまたは 2 つの物理パーティションのみを必要とします。

コンテナーがいくつかの物理パーティションに拡張される可能性がある場合は、クロスパーティション クエリを最小化するパーティション キーを選択する必要があります。 次のいずれかに該当する場合、コンテナーにはいくつかの物理パーティションが必要になります。

  • コンテナーは 30,000 RU を超えてプロビジョニングされる

  • コンテナーが 100 GB を超えるデータを格納する

パーティション キーとして項目 ID を使用する

コンテナーに、有効な値が広範囲にわたるプロパティがある場合は、パーティション キーの選択肢として優れたものがあります。 このようなプロパティの 1 つの例として、項目 ID があります。 サイズが小さく読み取り負荷の高いコンテナー、または、あらゆるサイズの書き込みの多いコンテナーの場合、項目 ID は、必然的にパーティション キーに適しています。

"項目 ID" のシステム プロパティは、コンテナー内のすべての項目に存在します。 項目の論理 ID を表す他のプロパティがある場合があります。 多くの場合、これらは 項目 ID と同じ理由で、パーティション キーとして選択することに適しています。

項目 ID は、次のような理由でパーティション キーの選択肢として適しています。

  • 有効な値の範囲が幅広い (項目ごとに 1 つの一意の 項目 ID)。
  • 項目ごとに一意の 項目 ID があるので、項目 ID は、RU の消費量とデータ ストレージを均等に分散するため。
  • 項目 ID がわかっている場合は、項目のパーティション キーが常にわかっているため、効率的なポイント読み取りを簡単に行うことができます。

項目 ID をパーティション キーとして選択する場合は、次の点に注意してください。

  • 項目 ID がパーティション キーの場合は、コンテナー全体を通じての一意識別子になります。 項目 ID が重複している項目は存在できません。
  • 大量の 物理パーティションを含む読み取り負荷の高いコンテナーがある場合、項目 ID を持つ等値フィルターを使用するクエリの方が効率的になります。
  • 複数の論理パーティションでストアド プロシージャまたはトリガーを実行することはできません。

次のステップ