Cloud Firestore のインデックスの種類

インデックスは、データベースのパフォーマンスにおける重要な要素です。書籍内のトピックをページ番号に対応付ける書籍の索引(インデックス)と同様に、データベースのインデックスはデータベース内のアイテムをデータベース内の場所にマッピングします。データベースにクエリを送信する際に、データベースがインデックスを使用すると、リクエストされたアイテムの場所をすばやく検索できます。

このページでは、Cloud Firestore で使用される単一フィールド インデックス複合インデックスの 2 種類のインデックスについて説明します。

すべてのクエリの背後にインデックスが存在

クエリを実行する際にインデックスが存在しないと、ほとんどのデータベースではアイテムごとにデータベースのコンテンツ全体をクロールすることになるため、データベースが大きくなるにつれて処理が大幅に遅くなります。Cloud Firestore では、すべてのクエリにインデックスを使用することで、クエリの高パフォーマンスを確保します。その結果、クエリのパフォーマンスは結果セットのサイズに依存することになり、データベース内のアイテム数には依存しません。

インデックス管理の手間を減らし、アプリ開発により注力する

Cloud Firestore には、インデックスの管理にかかる時間を短縮できる機能があります。最も基本的なクエリに必要なインデックスは、自動的に作成されます。Cloud Firestore は、アプリを使用してテストする際に、アプリで必要な追加のインデックスを識別して作成するのに役立ちます。

単一フィールド インデックス

単一フィールド インデックスは、特定の 1 つのフィールドを使用して、コレクション内のすべてのドキュメントの並べ替え済みマッピングを保持します。単一フィールド インデックスの各エントリは、ドキュメント内の特定のフィールドの値と、そのドキュメントのデータベース内での位置を記録します。

Cloud Firestore はドキュメントの各フィールドに対して、2 つの単一フィールド インデックスを自動的に定義して維持します。1 つは昇順(arrow_upward)で、もう 1 つは降順(arrow_downward)です。マップ オブジェクトが含まれるフィールドに関しては、Cloud Firestore は、マップ内の各サブフィールドに対して 1 つの昇順インデックスと 1 つの降順インデックスを作成します。

Cloud Firestore はこれらのインデックスを自動的に作成するため、アプリケーションでは最も基本的なデータベース クエリを迅速にサポートできます。単一フィールド インデックスを使用すると、フィールドの値と、比較演算子 <<===>=> に基づいて単純なクエリを実行できます。

説明のために、インデックス作成の観点から cities の例について考えます。次の例では、cities コレクション内にいくつかの city ドキュメントを作成し、各ドキュメントに namestatecountrycapitalpopulation フィールドを設定しています。

ウェブ
var citiesRef = db.collection("cities");

citiesRef.doc("SF").set({
    name: "San Francisco", state: "CA", country: "USA",
    capital: false, population: 860000 });
citiesRef.doc("LA").set({
    name: "Los Angeles", state: "CA", country: "USA",
    capital: false, population: 3900000 });
citiesRef.doc("DC").set({
    name: "Washington, D.C.", state: null, country: "USA",
    capital: true, population: 680000 });
citiesRef.doc("TOK").set({
    name: "Tokyo", state: null, country: "Japan",
    capital: true, population: 9000000 });
citiesRef.doc("BJ").set({
    name: "Beijing", state: null, country: "China",
    capital: true, population: 21500000 });

set オペレーションが実行されるたびに、Cloud Firestore は各フィールドの 2 つの単一フィールド インデックスを更新します。次の表の各行に、単一フィールド インデックスを示します。

コレクション インデックス登録されるフィールド
cities arrow_upward name
cities arrow_downward name
cities arrow_upward state
cities arrow_downward state
cities arrow_upward country
cities arrow_downward country
cities arrow_upward capital
cities arrow_downward capital
cities arrow_upward population
cities arrow_downward population

自動的に作成されるこれらのインデックスを使用すると、次のようなシンプルなクエリを実行できます。

ウェブ
citiesRef.where("state", "==", "CA")
citiesRef.where("population", "<", 100000)
citiesRef.where("name", ">=", "San Francisco")

また、等式(==)に基づいて複合クエリを作成することもできます。

ウェブ
citiesRef.where("state", "==", "CO").where("name", "==", "Denver")
citiesRef.where("country", "==", "USA").where("capital", "==", false).where("state", "==", "CA").where("population", "==", 860000)

範囲比較(<<=>>=)を使用する複合クエリを実行する必要がある場合、または別のフィールドにより並べ替える必要がある場合は、そのクエリ用の複合インデックスを作成する必要があります。

複合インデックス

複合インデックスは単一フィールド インデックスと同様に、コレクション内のすべてのドキュメントの並べ替え済みマッピングを保持します。ただし、マッピングには単一のフィールドではなく、複数のフィールドが含まれます。複合インデックスは、その各フィールドの並べ替えモード(昇順または降順)も定義します。インデックスはこれらの並べ替えモードに基づいて並べ替えられます。Cloud Firestore では複合インデックスを使用して、単一フィールド インデックスではサポートされない複合クエリをサポートします。たとえば、次のクエリには複合インデックスが必要です。

ウェブ
citiesRef.where("country", "==", "USA").orderBy("population", "asc")
citiesRef.where("country", "==", "USA").where("population", "<", 3800000)
citiesRef.where("country", "==", "USA").where("population", ">", 690000)

これらのクエリには、以下に示す複合インデックスが必要です。これらのクエリでは country フィールドに対して等式を使用しているため、このフィールドの並べ替えモードは降順と昇順のどちらでもかまいません。デフォルトでは、不等式クエリは、不等式句のフィールドに基づいて昇順を適用します。

コレクション インデックス登録されるフィールド
cities arrow_upward(または arrow_downward)country、arrow_upward population

Cloud Firestore では、可能なフィールドの組み合わせの数が多くなるため、単一フィールド インデックスの場合とは異なり、複合インデックスの自動作成は行いません。代わりに、Cloud Firestore は、アプリを作成する際に必要な複合インデックスを特定して作成できるようにします。

最初に必要なインデックスを作成せずに上記のクエリを実行しようとすると、Cloud Firestore はリンクが含まれたエラー メッセージを返します。そのリンク先にアクセスすることによって、不足しているインデックスを作成できます。この動作は、インデックスでサポートされていないクエリを試行するたびに発生します。また、コンソールまたは Firebase CLI を使用することで、複合インデックスを手動で定義して管理することもできます。インデックスの作成と管理の詳細については、インデックスの管理をご覧ください。

同じクエリを実行するけれども並べ替えが降順の場合は、population 用に降順方向の複合インデックスを追加する必要があります。

ウェブ
citiesRef.where("country", "==", "USA").orderBy("population", "desc")

citiesRef.where("country", "==", "USA")
         .where("population", "<", 3800000)
         .orderBy("population", "desc")

citiesRef.where("country", "==", "USA")
         .where("population", ">", 690000)
         .orderBy("population", "desc")
コレクション インデックス登録されるフィールド
cities arrow_upward country、arrow_upward population
cities arrow_upward countryarrow_downward population

インデックスと価格

インデックスはアプリケーションのストレージの費用の対象です。インデックスのストレージ サイズの計算方法の詳細については、インデックス エントリのサイズをご覧ください。

インデックス マージの活用

Cloud Firestore ではすべてのクエリにインデックスを使用しますが、クエリごとに必ず 1 つのインデックスが必要になるわけではありません。複数の等式(==)句(およびオプションで orderBy 句)が含まれるクエリに対しては、Cloud Firestore は既存のインデックスを再利用できます。Cloud Firestore では、シンプルな等式フィルタのインデックスをマージして、より大規模な等式クエリに必要な複合インデックスを作成できます。

インデックス マージを利用できる状況を特定すると、インデックスの費用を削減できます。たとえば、レストランを評価するアプリに restaurants というコレクションがある場合を考えます。

  • collections_bookmark restaurants

    • class burgerthyme

      name : "Burger Thyme"
      category : "burgers"
      city : "San Francisco"
      editors_pick : true
      star_rating : 4

ここで、このアプリは以下のようなクエリを使用するとします。categorycityeditors_pick に等式句の組み合わせを使用し、並べ替えは常に star_rating の昇順です。

ウェブ
db.collection("restaurants").where("category", "==", "burgers")
                            .orderBy("star_rating")

db.collection("restaurants").where("city", "==", "San Francisco")
                            .orderBy("star_rating")

db.collection("restaurants").where("category", "==", "burgers")
                            .where("city", "==", "San Francisco")
                            .orderBy("star_rating")

db.collection("restaurants").where("category", "==", "burgers")
                            .where("city", "==" "San Francisco")
                            .where("editors_pick", "==", true )
                            .orderBy("star_rating")

それぞれのクエリに対してインデックスを作成するという方法が考えられます。

コレクション インデックス登録されるフィールド
restaurants arrow_upward category、arrow_upward star_rating
restaurants arrow_upward city、arrow_upward star_rating
restaurants arrow_upward category、arrow_upward city、arrow_upward star_rating
restaurants arrow_upward category、arrow_upward city、arrow_upward editors_pick、arrow_upward star_rating

より適切なソリューションとして、等式句のインデックスをマージする Cloud Firestore の機能を利用することにより、インデックスの数を減らすことができます。

コレクション インデックス登録されるフィールド
restaurants arrow_upward category、arrow_upward star_rating
restaurants arrow_upward city、arrow_upward star_rating
restaurants arrow_upward editors_pick、arrow_upward star_rating

このインデックス セットはサイズが小さくなっただけでなく、次のような追加のクエリもサポートします。

ウェブ
db.collection("restaurants").where("editors_pick", "==", true)
                            .orderBy("star_rating")

インデックスの制限事項

インデックスには以下の制限が適用されます。すべての割り当てと制限の詳細については、割り当てと制限をご覧ください。

制限 詳細
ドキュメントの複合インデックス エントリの最大合計サイズ 2 MiB
データベースの複合インデックスの最大数 200

ドキュメントごとのインデックス エントリの最大数

20,000

インデックス エントリの数は、ドキュメントに関する次の数の合計です。

  • 単一フィールド インデックス エントリ数
  • 複合インデックス エントリ数

Cloud Firestore は各フィールドに対して、2 つの単一フィールド インデックス エントリ(昇順インデックスのエントリ 1 つ、降順インデックスのエントリ 1 つ)を自動的に作成します。

上限 20,000 という前提の下で、各ドキュメントには最大 10,000 からドキュメントの複合インデックス エントリ数を差し引いたフィールドのインデックスを作成できます。

インデックス エントリの最大サイズ

1,500 バイト

1,500 バイトを超えるインデックス エントリは切り捨てられます。切り捨てられたインデックス値が含まれるクエリからは、整合性のない結果が返されることがあります。

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。