Azure Cosmos DB で複合インデックスを活用する 3 つの方法

2019年9月19日 に投稿済み

Program Manager, Azure Cosmos DB

Microsoft Build 2019 で、複合インデックスが Azure Cosmos DB に導入されました。最新のサービス更新により、複合インデックスを活用できるクエリの種類が増えます。このブログ記事では、複合インデックスについて説明し、一般的なユース ケースを紹介します。

Azure Cosmos DB のインデックスの種類

Azure Cosmos DB には現在、以下のインデックスの種類があり、それぞれ以下のクエリの種類に使用します。

範囲インデックス:

  • 等値クエリ
  • 範囲クエリ
  • 1 つのプロパティに対する ORDER BY クエリ
  • JOIN クエリ

空間インデックス:

  • 地理空間機能

複合インデックス:

  • 複数のプロパティに対する ORDER BY クエリ
  • フィルターおよび ORDER BY 句を含むクエリ
  • 複数のプロパティに対するフィルターを含むクエリ

複合インデックスのユース ケース

既定では、Azure Cosmos DB では各プロパティに対して範囲インデックスが作成されます。多くのワークロードではこのインデックスで十分で、さらなる最適化は必要ありません。複合インデックスは、既定の範囲インデックスに追加できます。複合インデックスでは、その複合インデックス内の各プロパティに対して、パスと順序 (ASC または DESC) の両方が定義されます。

複数のプロパティに対する ORDER BY クエリ

クエリに 2 つ以上のプロパティを持つ ORDER BY 句がある場合、複合インデックスが必要です。たとえば次のクエリでは、age と name に複合インデックスを定義する必要があります (age ASC, name ASC)。

SELECT * FROM c ORDER BY c.age ASC, c.name ASC

このクエリでは、すべての結果が age プロパティの値の昇順で並べ替えられます。age の値が同じドキュメントが 2 つある場合、ドキュメントは name の順に並べ替えられます。

フィルターおよび ORDER BY 句を含むクエリ

クエリに別々のプロパティに対するフィルターと ORDER BY 句がある場合、複合インデックスを使用するとパフォーマンスが向上します。たとえば次のクエリでは、name と age に対する複合インデックスを定義し、クエリを更新して ORDER BY 句に name を含めるようにすると、必要な要求ユニット (RU) が少なくなります。

元のクエリ (範囲インデックスを使用):

SELECT * FROM c WHERE c.name = “Tim” ORDER BY c.age ASC

変更後のクエリ (name と age に対する複合インデックスを使用):

SELECT * FROM c WHERE c.name = “Tim” ORDER BY c.name ASC, c.age ASC

複合インデックスによってクエリのパフォーマンスは大幅に向上しますが、複合インデックスのない元のクエリも正常に実行できます。複合インデックスがある変更後のクエリを実行すると、ドキュメントが age プロパティの順に並べ替えられます。フィルターに一致するすべてのドキュメントは name 値が同じなので、age の昇順で返されるのです。

複数のプロパティに対するフィルターを含むクエリ

クエリに 2 つ以上のプロパティに対するフィルターがある場合、複合インデックスを追加するとパフォーマンスが向上します。

次のクエリについて考えてみましょう。

SELECT * FROM c WHERE c.name = “Tim” and c.age > 18

(name ASC, age ASC) に対する複合インデックスがないので、このクエリでは範囲インデックスを使用します。name と age に対する複合インデックスを作成することで、このクエリの効率を向上できます。

複数の等値フィルターと最大でも 1 つの範囲フィルター (>、<、<=、>=、!= など) があるクエリでは、複合インデックスが使用されます。クエリで複合インデックスをフルに活用できない場合、定義済みの複合インデックスと範囲インデックスの組み合わせが使用されます。詳細については、インデックス作成ポリシーに関するドキュメントを参照してください。

複合インデックスがもたらすパフォーマンス上のメリット

複合インデックスがもたらすパフォーマンスのメリットを紹介するために、いくつかのサンプル クエリを実行できます。ここでは、Azure Cosmos DB ラボで使用している栄養データセットを使用します。

この例では、フィルターと ORDER BY 句の両方があるクエリを最適化します。まず、既定のインデックス作成ポリシーで開始します。このポリシーでは、すべてのプロパティに対して範囲インデックスが作成されます。以下の Azure Portal の画像で参照されているクエリを実行すると、クエリのメトリックが表示されます。

クエリのメトリック:

既定の範囲インデックスを使用し、21.8 RU を消費するクエリ。

既定のインデックス作成ポリシーを使用するこのクエリでは、21.8 RU が必要でした。

foodGroup と _ts に複合インデックスを追加して、ORDER BY 句に foodGroup が含まれるようにクエリのテキストを更新すると、クエリの RU 使用量が大幅に減少しました。

クエリのメトリック:

複合インデックスを使用し、4.07 RU を消費するクエリ。

複合インデックスを追加すると、クエリの RU は 21.8 RU からわずか 4.07 RU に減少しました。このクエリ最適化は、合計データ サイズが増えるに従って、特に大きな影響があります。ORDER BY 句のプロパティのカーディナリティが高い場合、複合インデックスのメリットが大きくなります。

複合インデックスの作成

複合インデックスの作成の詳細については、リンク先のドキュメントをご覧ください。Azure Portal を通じて直接インデックス作成ポリシーを更新するのがシンプルです。すでに Azure Cosmos DB 内にあるデータに対して複合インデックスを作成する場合、インデックス更新の際、通常操作で余った RU が使用されます。新しいインデックス作成ポリシーを定義すると、Azure Cosmos DB により、プロパティへの書き込みの際に、自動的に複合インデックスが作成されます。

お客様の既存の Azure Cosmos DB ワークロードで、複合インデックスによって RU の使用率が向上するかどうかをお調べください。