【Microsoft Azure】Cosmos DBのパーティションをマスターする!

こんにちは。今日は、Microsoft Azureで提供されている独自のデータベースである、Cosmos DBに関する記事です。Cosmos DBにはPartition Keyという概念があるのですが、何度調べても都度忘れてしまうので、未来の自分のためにも整理して記事に残しておこうと思います。

それでは早速参ります。

参考文献:

https://docs.microsoft.com/ja-jp/azure/cosmos-db/partitioning-overview

答えはほとんど公式ドキュメントに書かれていますので、まだ読まれたことのない方は、一読されることをお勧めいたします!

Contents

論理パーティションと物理パーティション

パーティションの概念を理解するためには、まず物理パーティションと論理パーティションを理解する必要があります。公式ドキュメントの以下の図が、これらの関係をよく表しています。

公式ドキュメントより

論理パーティションとは、データの論理的な分類になります。そして、この論理的な分類の基準とするキーが「パーティションキー」となります。

以下に具体の説明がありますが、上記の図に当てはめると、CityをPartition Keyとしていた場合、Cityの値1つ1つが論理パーティションとなります。例えば、CityがLondonのデータは論理パーティションA、CityがNew Yorkのデータは論理パーティションB・・・といった具合です。

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

公式ドキュメントより

気になるところは色々あると思いますが、一旦続けて物理パーティションの説明です。

物理パーティションは、1つ以上の論理パーティションを含んでおり、実際のデータベースへのトランザクションの分散のために用いられる物理的な管理単位です。

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

公式ドキュメントより

物理パーティションは、スループット及び物理パーティション内のデータ増加に伴い、自動的に分割されていきます。

コンテナー内の物理パーティションの合計数に制限はありません。 プロビジョニングされたスループットまたはデータ サイズが増加すると、Azure Cosmos DB によって既存のパーティションが分割され、新しい物理パーティションが自動的に作成されます。 

公式ドキュメントより

論理パーティションは利用者のパーティションキーによってユーザが制御できるのに対し、物理パーティションは、CosmosDBのサービスにより制御されるため、ユーザが制御することはできません。

しかし、それぞれの物理パーティションへのスループット、及びデータ量は、論理パーティションの設計に多分に影響されることになるため、論理パーティションの設計は非常に重要です。

次のセクションでは、論理パーティション(パーティションキー)の設計プラクティスについて確認しておきます。

ちなみに、上の図では、さらにPartition Setという概念が登場していますが、これは、物理パーティションは、さらに複数リージョンで自動的に冗長化され、可用性が高められていることを意味しています。

各物理パーティションは、一連のレプリカで構成されます (“レプリカ セット” とも呼ばれます)。 各レプリカ セットによって、データベース エンジンのインスタンスがホストされます。 レプリカ セットにより、物理パーティション内に格納されたデータの耐久性、高可用性、一貫性が確保されます。

公式ドキュメントより

論理パーティション(パーティションキー)の設計プラクティス

高カーディナリティ & 均等データ量・トランザクションなキーを選ぶ

公式ドキュメントにて、一般的な論理パーティションの設計プラクティスについて、以下のように説明されています。

—————

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

  • 値が変更されないプロパティであること。 プロパティがパーティション キーの場合、そのプロパティの値を更新することはできません。
  • 高いカーディナリティがあること。 言い換えると、プロパティには、有効な値が広範囲に及ぶことが必要です。
  • 要求ユニット (RU) の消費量とデータ ストレージをすべての論理パーティションに均等に分散すること。 これにより、物理パーティション全体でも RU の消費とストレージの分散が保証されます。

—————

特に2、3点目が重要で、これはつまり、値のバリエーションが多く、かつ特定の論理パーティションにデータ量はトランザクションが集中しないようなキーを選択する必要がある、ということを言っています。

例えば、最初の例で、値のバリエーションが1つしかない場合は、物理パーティションを分割することができなくなってしまいます。また、バリエーションが2つ(London、NYC)あったとしても、Londonのデータが圧倒的に多い、もしくはLondonのデータへのアクセスが圧倒的に多い場合には、これまた物理パーティションの分割によりLondonのデータに対する負荷を軽減させることができません。

加えて、クエリで頻繁に利用される条件項目をキーも考慮する

また、クエリのパフォーマンスが重要な場合には、加えて検索キーで共通で利用される項目をパーティションキーに設定しておくことが有効とのことです。

検索キー項目をパーティションキーにすることで、検索キー項目の値ごとに所属する物理パーティションが決まることになります。こうすることで、トランザクションの結果が格納される物理パーティションへの迅速なルーティングが可能になります。(逆にいうと、物理パーティションを跨いでデータを探しにいく必要がある場合、パフォーマンスが落ちるということ)

https://docs.microsoft.com/ja-jp/azure/cosmos-db/partitioning-overview#partition-keys-for-read-heavy-containers

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

公式ドキュメントより

項目IDをキーにしてしまう

2点目のクエリ条件の点は置いておいて、1点目のTipsを最も簡単に実現できる方法が一意なあたいを持つ項目ID(連番、など)をパーティションキーにしてしまうことです。

項目IDの値は重複することがないので、これが最もカーディナリティが高く、均等なデータ量を実現できますね。

https://docs.microsoft.com/ja-jp/azure/cosmos-db/partitioning-overview#using-item-id-as-the-partition-key

以上、CosmosDBのパーティションの概念と、設計プラクティスに関する理解の整理でした!

おしまい

この記事を気に入っていただけたらシェアをお願いします!
ABOUT US
Yuu113
初めまして。ゆうたろうと申します。 兵庫県出身、東京でシステムエンジニアをしております。現在は主にデータ分析、機械学習を活用してビジネスモデリングに取り組んでいます。 日々学んだことや経験したことを整理していきたいと思い、ブログを始めました。旅行、カメラ、IT技術、江戸文化が大好きですので、これらについても記事にしていきたいと思っています。