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 句を含むクエリ
  • 2 つ以上のプロパティに対するフィルターを含むクエリ

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

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 プロパティの値に基づいて昇順で並べ替えられます。2つのドキュメントで age の値が同じ場合は、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 の使用率が向上するかどうかをご確認ください。