インデックスの概要
このページでは、MongoDB 互換の Firestore のインデックス作成について説明します。MongoDB 互換の Firestore では、デフォルトでインデックスは作成されません。データベースのパフォーマンスを向上させるには、最もよく使用されるクエリのインデックスを作成します。
インデックスは、データベースのパフォーマンスに大きな影響を与えます。クエリにインデックスが設定されている場合、スキャンする必要があるデータ量を減らし、結果の並べ替えに必要な作業を減らすことで、データベースから効率的に結果を返すことができます。ただし、インデックス エントリはストレージ コストと、インデックス付きフィールドに対する書き込みオペレーション中に実行される作業量を増やします。
インデックスの定義と構造
インデックスは次の要素で構成されます。
- コレクション ID
- 指定されたコレクション内のフィールドのリスト
- 各フィールドの順序(昇順または降順)
インデックスでは、スパース、マルチキー、一意のオプションを有効にすることもできます。
インデックスの順序
インデックスは、各フィールドの順序と並べ替えの方向によって一意に定義されます。たとえば、次のインデックスは 2 つの異なるインデックスであり、互換性はありません。
| コレクション | フィールド |
|---|---|
| cities | country(昇順)、population(降順) |
| cities | population(降順)、country(昇順) |
クエリをサポートするインデックスを作成する場合は、クエリと同じ順序でフィールドを含めます。
インデックス密度
デフォルトでは、インデックス エントリにはコレクション内のすべてのドキュメントのデータが格納されます。これは、非スパース インデックスと呼ばれます。ドキュメントにインデックスで指定されたフィールドが含まれているかどうかに関係なく、ドキュメントのインデックス エントリが追加されます。 存在しないフィールドは、インデックス エントリの生成時に null 値を持つものとして扱われます。この動作を変更するには、インデックスをスパース インデックスとして定義します。
スパース インデックス
スパース インデックスは、インデックス付きフィールドの少なくとも 1 つに値(null を含む)を含んでいるコレクション内のドキュメントのみをインデックスに登録します。スパース インデックスにより、ストレージの費用を削減して、パフォーマンスを向上させることができます。
配列値のマルチキー インデックス
配列値を含むフィールドにインデックスを作成する場合は、マルチキー インデックスを作成する必要があります。通常のインデックスでは、配列値をインデックスに登録できません。マルチキー インデックスは、インデックス定義で最大 1 つの配列フィールドをサポートしており、配列値を走査するオペレーションに使用できます。
マルチキー インデックスは、配列値をインデックスに登録する必要があることがわかっている場合にのみ使用してください。 通常のインデックスは、クエリを処理するときに便利です。たとえば、通常のインデックスは特定の範囲内の値を効率的にフィルタできます。
次の状況で配列値とマルチキー インデックスを操作すると、エラーが発生します。
- 通常のインデックスで登録されたフィールドに配列値を追加しようとした場合。配列値を追加するには、そのフィールドの既存の通常のインデックスを削除し、マルチキー インデックスとして再作成する必要があります。
- 配列値を含むフィールドに通常のインデックスを作成しようとした場合。マルチキー インデックスを作成するか、配列値を削除する必要があります。
- 配列値を持つ複数のフィールドにインデックスを登録しようとしています。マルチキー インデックスに配列値を持つフィールドを複数含めることはできません。 続行するには、データモデルまたはインデックス定義を変更します。
- 2 つのフィールド パスが
users.postsやusers.zipなどの共通の接頭辞を共有するマルチキー インデックスを作成しようとした場合
一意のインデックス
一意のインデックス オプションを設定して、インデックス付きフィールドに一意の値を適用します。 複数のフィールドにインデックスが設定されている場合、値の各組み合わせはインデックス全体で一意である必要があります。データベースは、重複する値のインデックス エントリを作成しようとする更新オペレーションや挿入オペレーションを拒否します。インデックス付きフィールドのデータに重複する値が含まれており、一意のインデックスを作成しようとすると、インデックスの構築が失敗し、オペレーションの詳細にエラー メッセージが表示されます。
一意のインデックス内の欠落しているフィールド
一意のインデックスに欠落しているフィールドがあるドキュメントを挿入すると、インデックスは欠落しているフィールドに null 値を設定します。生成されたインデックス エントリは一意である必要があります。一意でない場合、オペレーションは失敗します。
たとえば、次のインデックスがあるとします。
db.cities.createIndex( { "name": 1 }, { unique: true } )
ドキュメント {"abbreviation": "LA"} をコレクションに追加すると、一意のインデックスによって name が null に設定されたエントリが作成されます。その後、ドキュメント {"abbreviation": "NYC"} を追加しようとすると、一意のインデックスの結果エントリが同じになるため、オペレーションは失敗します。
複数のフィールドを含む一意のインデックスに同じ動作が適用されます。ドキュメントを作成または更新するときに、インデックス付きフィールドが欠落している場合は null に設定され、結果のインデックス エントリはインデックス内で一意である必要があります。
配列値の一意のインデックス
一意のマルチキー インデックスを使用すると、ドキュメントに重複する配列要素がないことを強制できます。
このタイプのインデックスでは、配列に単一のドキュメント内で一意の値が含まれていることは保証されません。
たとえば、一意のインデックスを使用する場合:
db.collection.createIndex( { "tags": 1 }, { unique: true } )
次のドキュメントは挿入できます。
{
"_id": 1,
"tags": [ "news", "tech", "news", "music" ]
}
インデックスでは、単一ドキュメントの同じ配列内で重複値("news")が許可されます。
重複する要素を含む 2 つ目のドキュメントを挿入しようとすると、オペレーションは失敗します。
{
"_id": 2,
"tags": [ "sports", "music" ]
}
"music" はドキュメント 1 の配列にすでに存在し、インデックスにマッピングされているため、オペレーションは失敗します。
1 つのドキュメント内の同じ配列内の要素が一意であることを確認する必要がある場合は、$push ではなく $addToSet などの更新演算子を使用して、アプリケーション ロジックで処理します。
空の配列、欠落しているフィールド、null 値
通常、一意のインデックス内の欠落しているフィールドは null として扱われ、ドキュメント間で一意である必要があります(一意のインデックス内の欠落しているフィールドをご覧ください)。ただし、配列フィールドの一意のインデックスの場合:
- 空の配列、欠落しているフィールド、スタンドアロンの null: 配列フィールドが空の場合、完全に欠落している場合、またはスタンドアロンの
null値(配列内ではない)を保持している場合、ドキュメントのインデックス キーは生成されません。そのため、複数のドキュメントに空のフィールドやスタンドアロンのnull値を含めることができます。重複キーエラーは発生しません。 - 配列内の null 要素: 配列に要素として
null値(["news", null]など)が含まれている場合、null要素はインデックス登録されます。インデックス付き配列フィールドにnull要素を含む後続のドキュメントは、重複キーエラーで失敗します。
TTL インデックス
TTL インデックスを使用して、データベースから古いデータを自動的に削除します。TTL インデックスは、特定のフィールドを、特定のコレクション内のドキュメントの有効期限として指定します。TTL を使用すると、古いデータをクリーンアップすることでストレージ費用を削減できます。 データは通常、有効期限が切れた後 24 時間以内に削除されます。
インデックス構築エラーのトラブルシューティング
インデックスを管理するときに、インデックス構築エラーが発生することがあります。データベースがデータで問題を検出すると、インデックス作成オペレーションに失敗する可能性があります。 インデックス作成オペレーションは、次の理由で失敗することがあります。
- インデックスの上限に達しました。たとえば、オペレーションでドキュメントあたりの最大インデックス エントリ数に達した可能性があります。インデックスの作成に失敗すると、エラー メッセージが表示されます。インデックスの上限に達していない場合は、インデックス オペレーションを再試行します。
- マルチキー インデックスが必要です。インデックス付きフィールドの少なくとも 1 つに配列値が含まれています。続行するには、マルチキー インデックスを使用するか、配列値を削除する必要があります。
- 配列値を持つ複数のフィールドにインデックスを登録しようとしています。マルチキー インデックスに配列値を持つフィールドを複数含めることはできません。 続行するには、データモデルまたはインデックス定義を変更します。
- 一意のインデックス オプションを設定しており、インデックス付きフィールドのデータで重複するインデックス エントリが作成されます。続行するには、重複する値の組み合わせをデータから削除します。
次のステップ
- インデックスの作成と管理の方法、またはTTL インデックスの作成と管理の方法を確認する