クエリ可能なフィールドには常にインデックスが作成されている必要がある
述語と集計に基づく読み取り操作は、対応するフィルターのインデックスを参照します。 インデックスがない場合、データベース エンジンはドキュメント スキャンを実行して、一致するドキュメントを取得します。 スキャンは常にコストがかかり、コレクション内のデータ量が増えるにつれて徐々にコストが高くなります。 クエリのパフォーマンスを最適化するために、すべてのクエリ可能なフィールドに対してインデックスを常に作成する必要があります。
不要なインデックスを回避し、既定ですべてのフィールドにインデックスを作成する
インデックスは、クエリ可能なフィールドに対してのみ作成する必要があります。 ワイルドカード インデックス作成は、ドキュメント構造内のフィールドがクエリ フィルターの一部になる可能性があるクエリ パターンが予測できない場合にのみ使用する必要があります。
ヒント
Azure DocumentDB では、既定で _id フィールドにのみインデックスが作成されます。 その他のフィールドはすべて、既定ではインデックス付けされません。 インデックスを作成するフィールドは、インデックスが多すぎるフィールドからの書き込みへの影響を最小限に抑えながら、クエリのパフォーマンスを最大化するために事前に計画する必要があります。
新しいドキュメントが初めて挿入されたとき、または既存のドキュメントが更新または削除されると、インデックス内の指定された各フィールドも更新されます。 インデックス作成ポリシーに多数のフィールド (またはドキュメント内のすべてのフィールド) が含まれている場合、対応するインデックスの更新でサーバーによって使用されるリソースが増えます。 大規模に実行する場合は、クエリ可能なフィールドにのみインデックスを作成し、クエリ述語で使用されていない残りのフィールドはすべてインデックスから除外する必要があります。
効率的なデータ インジェストのためのインデックス作成戦略
Azure DocumentDB への大規模なワークロード移行では、効率的に実行するために、データ読み込みの後にインデックスを作成することをお勧めします。 これにより、書き込みのオーバーヘッドが大幅に削減され、リソースの消費量が最小限に抑えられます。また、データ インジェストのパフォーマンスが向上します。 一括インジェスト中にインデックスを維持すると、各書き込み操作で該当するすべてのインデックスを更新する必要があります。そのため、挿入の速度が低下する可能性があります。
履歴データに対して複数のインデックスが作成された場合は、各フィールドに対して非ブロッキング createIndex コマンドを発行します
特にアプリケーションの要件が進化するにつれて、すべてのクエリ パターンを事前に計画できるわけではありません。 アプリケーションのニーズを変更するには、必要に応じて、大量の履歴データを含むクラスターのインデックスにフィールドを追加する必要があります。
このようなシナリオでは、サーバーからの応答を待たずに、各 createIndex コマンドを非同期的に発行する必要があります。
注
既定では、Azure DocumentDB は、インデックスが履歴データに基づいて完全に構築された後にのみ、createIndex 操作に応答します。 クラスターのサイズと取り込まれたデータの量によっては、時間がかかり、サーバーが createIndex コマンドに応答していないかのように見える場合があります。
Mongo シェルを使用して createIndex コマンドを発行する場合は、Ctrl + C キーを押してコマンドを中断し、応答の待機を停止し、次の操作セットを発行します。
注
CreateIndex コマンドの発行後に Ctrl + C キーを使用して中断しても、サーバーでのインデックスのビルド操作は終了しません。 シェルがサーバーからの応答を待機するのを停止するだけで、サーバーは既存のドキュメントに対してインデックスを非同期的に作成し続けます。
複数のフィールドに述語を持つクエリの複合インデックスを作成する
複合インデックスは、次のシナリオで使用する必要があります。
- 複数のフィールドにフィルターを適用したクエリ
- 複数のフィールドにフィルターを適用し、1 つ以上のフィールドを昇順または降順で並べ替えたクエリ
'cosmicworks' データベースの 'employee' コレクション内にある次のドキュメントについて考えましょう。
{
"firstName": "Steve",
"lastName": "Smith",
"companyName": "Microsoft",
"division": "Azure",
"subDivision": "Data & AI",
"timeInOrgInYears": 7
}
次のクエリを使用して、姓が「Smith」であり、組織に5年以上在籍しているすべての従業員を検索します。
db.employee.find({"lastName": "Smith", "timeInOrgInYears": {"$gt": 5}})
'lastName' と 'timeInOrgInYears' の両方の複合インデックスによって、このクエリが最適化されます。
use cosmicworks;
db.employee.createIndex({"lastName" : 1, "timeInOrgInYears" : 1})
createIndex 操作の状態を追跡する
インデックスが追加され、履歴データにインデックスを作成する必要がある場合は、db.currentOp() を使用してインデックス作成操作の進行状況を追跡できます。
このサンプルを検討して、'cosmicworks' データベースのインデックス作成の進行状況を追跡します。
use cosmicworks;
db.currentOp()
createIndex 操作が進行中の場合、応答は次のようになります。
{
"inprog": [
{
"shard": "defaultShard",
"active": true,
"type": "op",
"opid": "30000451493:1719209762286363",
"op_prefix": 30000451493,
"currentOpTime": "2024-06-24T06:16:02.000Z",
"secs_running": 0,
"command": { "aggregate": "" },
"op": "command",
"waitingForLock": false
},
{
"shard": "defaultShard",
"active": true,
"type": "op",
"opid": "30000451876:1719209638351743",
"op_prefix": 30000451876,
"currentOpTime": "2024-06-24T06:13:58.000Z",
"secs_running": 124,
"command": { "createIndexes": "" },
"op": "workerCommand",
"waitingForLock": false,
"progress": {},
"msg": ""
}
],
"ok": 1
}
大きなインデックス キーを既定で有効にする
ドキュメントに多数の文字を持つキーが含まれていない場合や、ドキュメントに複数のレベルの入れ子が含まれていない場合でも、大きなインデックス キーを指定すると、これらのシナリオが確実にカバーされます。 これで、大きなインデックス キーがエンジンの既定の動作になりました。
このサンプルでは、'cosmicworks' データベースの 'large_index_coll' コレクションで大きなインデックス キーを有効にすることを考慮してください。
use cosmicworks;
db.runCommand(
{
"createIndexes": "large_index_coll",
"indexes": [
{
"key": { "ikey": 1 },
"name": "ikey_1",
"enableLargeIndexKeys": true
}
]
})
ブロッキング オプションを使用した新しい書き込み操作に対するインデックス ビルドの優先順位付け
データが読み込まれる前にインデックスを作成する必要があるシナリオでは、ブロック オプションを使用して、インデックスのビルドが完了するまで受信書き込みをブロックする必要があります。
{ "blocking": true }の設定は、データ書き込みを開始する前に空のコレクションにインデックスが作成される移行ユーティリティで役立ちます。
インデックス作成のブロッキングオプションの例を考えると、「cosmicworks」データベースの「employee」コレクションの場合です。
use cosmicworks;
db.runCommand({
createIndexes: "employee",
indexes: [{"key":{"name":1}, "name":"name_1"}],
blocking: true
})
関連コンテンツ
テキスト ベースのデータの効率的な検索とクエリを可能にするテキスト インデックス作成を確認します。