Azure Cosmos コンテナーを照会する

適用対象: SQL API

この記事では、Azure Cosmos DB のコンテナー (コレクション、グラフ、またはテーブル) のクエリを実行する方法について説明します。 特に、Azure Cosmos DB でのインパーティション クエリとクロスパーティション クエリの動作について説明します。

インパーティション クエリ

コンテナーのデータのクエリを実行するとき、クエリでパーティション キー フィルターを指定すると、Azure Cosmos DB によってクエリが自動的に最適化されます。 クエリは、フィルターで指定されているパーティション キーの値に対応する物理パーティションにルーティングされます。

たとえば、DeviceId に対する等値フィルターが含まれる次のようなクエリについて考えます。 DeviceId でパーティション分割されたコンテナーに対してこのクエリを実行すると、1 つの物理パーティションにフィルターされます。

SELECT * FROM c WHERE c.DeviceId = 'XMS-0001'

前の例と同様に、このクエリでも 1 つのパーティションにフィルターされます。 Location に対するフィルターを追加しても、これは変わりません。

SELECT * FROM c WHERE c.DeviceId = 'XMS-0001' AND c.Location = 'Seattle'

次に示すクエリでは、パーティション キーに対する範囲フィルターがあり、1 つの物理パーティションにスコープされません。 インパーティション クエリにするには、クエリにパーティション キーを含む等値フィルターが必要です。

SELECT * FROM c WHERE c.DeviceId > 'XMS-0001'

クロスパーティション クエリ

次のクエリには、パーティション キー (DeviceId) に対するフィルターがありません。 そのため、各パーティションのインデックスに対して実行されるすべての物理パーティションにファンアウトする必要があります。

SELECT * FROM c WHERE c.Location = 'Seattle`

各物理パーティションには、独自のインデックスがあります。 そのため、コンテナーに対してクロスパーティション クエリを実行すると、実質的には物理パーティション "ごと" に 1 つのクエリが実行されることになります。 Azure Cosmos DB によって、異なる物理パーティションに対する結果が自動的に集計されます。

異なる物理パーティション内のインデックスは、互いに独立しています。 Azure Cosmos DB にはグローバル インデックスはありません。

並列クロスパーティション クエリ

Azure Cosmos DB SDK 1.9.0 以降では、並列クエリ実行オプションがサポートされています。 並列パーティション間クエリを使用すれば、複数のパーティションにまたがるクエリでも、少ない待ち時間で実行できます。

次のパラメーターを調整することで、並列クエリの実行を管理できます。

  • MaxConcurrency: コンテナーのパーティションに対する同時ネットワーク接続数の上限を設定します。 このプロパティを -1 に設定した場合、SDK によって並列処理次数が管理されます。 MaxConcurrency0 に設定されている場合は、コンテナーのパーティションに対して 1 つのネットワーク接続が存在します。

  • MaxBufferedItemCount: クエリの待ち時間とクライアント側のメモリ使用率のバランスを調整します。 このオプションを省略するか -1 に設定した場合、並列クエリの実行中にバッファリングされる項目の数は SDK によって管理されます。

Azure Cosmos DB ではクロスパーティション クエリを並列化できるため、クエリの待機時間は通常、システムによって物理パーティションが追加されると適切にスケーリングされます。 一方、RU 使用量は、物理パーティションの合計数が増えるにつれて大幅に増加します。

クロスパーティション クエリを実行する場合、基本的には個別の物理パーティションごとに異なるクエリが実行されます。 クロスパーティション クエリでは、インデックスが利用可能な場合は使用されますが、インパーティション クエリほど効率的ではありません。

便利な例

次のような比喩を使うと、クロスパーティション クエリを理解しやすくなります。

異なるアパートに荷物を配達する必要がある配送ドライバーがいるものとします。 各アパートには建物のリストがあり、すべての居住者のユニット番号が示されています。 各アパートは物理パーティション、各リストは物理パーティションのインデックスと考えることができます。

この例を使用して、インパーティション クエリとクロスパーティション クエリを比較できます。

インパーティション クエリ

配送ドライバーが適切なアパート (物理パーティション) を認識している場合は、すぐに正しい建物に向かうことができます。 ドライバーは、アパートに対する居住者のユニット番号 (インデックス) のリストを確認し、適切な荷物を迅速に配達できます。 この場合、ドライバーは、あるアパートまで運転していって荷物の受取人がそこに住んでいるかどうかを確認するのに無駄な時間や労力を使わなくて済みます。

クロスパーティション クエリ (ファンアウト)

配送ドライバーが正しいアパート (物理パーティション) を知らない場合は、個々のすべてのアパートまで行き、すべての居住者のユニット番号 (インデックス) を含むリストを確認する必要があります。 各アパートに到着したら、各居住者の住所のリストを使用できます。 ただし、荷物の受取人がそこに住んでいるかどうかにかかわらず、すべてのアパートのリストを確認する必要があります。 これがクロスパーティション クエリの動作方法です。 インデックスを使用することはできますが (すべてのドアをノックする必要はありません)、すべての物理パーティションでインデックスを個別に確認する必要があります。

クロスパーティション クエリ (少数の物理パーティションにのみスコープされている)

荷物のすべての受取人が特定のいくつかのアパートに住んでいることを配送ドライバーが知っている場合、すべてのアパートに行く必要はありません。 いくつかのアパートに行くには 1 つの建物だけに行くより多くの作業が必要になりますが、それでもかなりの時間と労力を節約できます。 クエリのフィルターに IN キーワードでパーティション キーが含まれる場合、データに関連する物理パーティションのインデックスだけがチェックされます。

クロスパーティション クエリを回避する

ほとんどのコンテナーでは、いくつかのクロスパーティション クエリを使用することは避けられません。 少数のクロスパーティション クエリであれば問題ありません。 ほとんどすべてのクエリ操作では、パーティションをまたぐことが (論理パーティション キーと物理パーティションの両方) サポートされています。 また、Azure Cosmos DB では、複数の物理パーティションを対象とするクエリ実行を並列化するための多くの最適化が、クエリ エンジンとクライアント SDK に用意されています。

読み取り量の多いほとんどのシナリオでは、クエリ フィルターで最も一般的なプロパティを選択することをお勧めします。 また、パーティション キーが他のパーティション キー選択のベスト プラクティスに従っていることを確認する必要もあります。

通常、クロスパーティション クエリの回避は大規模なコンテナーだけの問題です。 物理パーティションのインデックスで結果を確認するたびに、クエリのフィルターと一致する項目が物理パーティションにない場合であっても、少なくとも約 2.5 RU の料金がかかります。 そのため、物理パーティションが 1 つだけ (または少数) の場合は、インパーティション クエリよりクロスパーティション クエリの方がはるかに多くの RU を使用するということはありません。

物理パーティションの数は、プロビジョニングされた RU の量に関連付けられています。 各物理パーティションでは、最大 10,000 RU をプロビジョニングでき、最大 50 GB のデータを格納できます。 物理パーティションは、Azure Cosmos DB によって自動的に管理されます。 コンテナー内の物理パーティションの数は、プロビジョニングされたスループットと使用されているストレージに依存します。

ワークロードが以下の条件を満たしている場合は、クロスパーティション クエリを避ける必要があります。

  • 30,000 より多くの RU をプロビジョニングする予定である
  • 100 GB を超えるデータを格納する予定である

次のステップ

Azure Cosmos DB でのパーティション分割については、次の記事を参照してください。