インデックス構築では、最適化された構築プロセスを使用し、インデックス構築の開始時と終了時にコレクションを排他ロックします。構築プロセスの残りの部分は、読み取り操作と書き込み (write) 操作のインターリーブによって一時停止されます。インデックス構築プロセスとロック動作の詳細については、 「インデックス構築プロセス」を参照してください。
レプリカセットまたはシャーディングされたクラスターに対するインデックスは、データを保持するすべてのレプリカセットメンバーに対して同時にビルドされます。プライマリには、データを保持する投票ノードについて、使用準備完了とインデックスをマークする前にビルドの完了が必要な、プライマリ自体を含めた最小数(コミットクォーラム)が設定されています。members[n].votes 「投票」ノードとは、 が0 より大きい任意のレプリカセットノードです。詳細については、 「レプリケートされた環境でのインデックス構築」 を参照してください。
注意
Atlas でのインデックス作成の詳細については、Atlas ドキュメントの「インデックス管理ページ 」を参照してください。
動作
フォアグラウンド構築とバックグラウンド構築との比較
MongoDBの以前のバージョンでは、フォアグラウンドまたはバックグラウンドでのインデックスのビルドがサポートされていました。フォアグラウンドでのインデックスビルドは高速で、より効率の高いインデックスデータ構造が生成されていましたが、ビルド中はインデックスされるコレクションの親データベースへの読取りおよび書込みアクセスをすべてブロックする必要がありました。バックグラウンドでのインデックスビルドは遅く、結果の効率も低いものでしたが、ビルド中にデータベースとそのコレクションへの読取りおよび書込みアクセスが可能でした。
インデックス構築では、構築の開始時と終了時にのみ、インデックスが作成されるコレクションに対して排他ロックが取得されるようになりました。構築プロセスの残りの部分では、バックグラウンドインデックス構築の生成動作を使用して、構築中にコレクションへの読み取りおよび書込みアクセスを最大化します。インデックスの構築では、ロック動作の制限が緩いにもかかわらず、効率的なインデックスデータ構造が生成されます。
最適化されたインデックス構築のパフォーマンスは、最低でもバックグラウンド インデックス構築と同等です。構築プロセス中に更新がほとんどまたはまったく受信されないワークロードの場合、最適化されたインデックス構築は、同じデータに対するフォアグラウンド インデックス構築と同じくらい高速になります。
進行中のインデックス構築の進行状況を監視するには、db.currentOp() を使用します。
MongoDB では、createIndexesまたはそのシェルヘルパーcreateIndex()createIndexes()に指定されている場合は background インデックス構築は無視されます。
インデックス構築中の制約違反
一意のインデックスなど、コレクションに制約を強制するインデックスの場合、 mongodはインデックスのビルド完了後に、既存のドキュメントと同時に書込まれたすべてのドキュメントをチェックし、それらの制約に違反しているかどうかをチェックします。 インデックス制約に違反するドキュメントは、インデックスのビルド中に存在する可能性があります。 ビルドの最後にインデックス制約に違反するドキュメントがある場合、 mongodはビルドを終了し、エラーをスローします。
たとえば、データが入ったコレクションinventoryを考えてみましょう。 管理者が、 product_skuフィールドに一意のインデックスを作成したいと考えています。 コレクション内のいずれかのドキュメントでproduct_skuの値が重複している場合でも、インデックスのビルドは正常に開始できます。 ビルドの最後に違反がまだ存在する場合、 mongodはビルドを終了し、エラーをスローします。
同様に、インデックス構築が進行中に、アプリケーションはproduct_sku の重複する値を持つドキュメントを inventoryコレクションに正常に書き込むことができます。
制約違反によるインデックス構築失敗のリスクを軽減するには、以下の対策を取ります。
コレクション内のドキュメントがどれもインデックス制約に違反していないことを検証します。
違反のない書き込み操作を保証できないアプリケーションからの、コレクションへの書き込みをすべて停止します。
シャーディングされたコレクション
複数のシャードに分散されたシャーディングされたコレクションの場合、1 つ以上のシャードに重複したドキュメントを含むチャンクが含まれる場合があります。そのため、インデックスの作成操作は、一部のシャード(重複のないシャード)では成功するものの、他のシャード(重複のあるシャード)では成功しない場合があります。シャード間で不整合なインデックスが残らないようにするには、 からdb.collection.dropIndex() mongosを発行して、コレクションからインデックスを削除します。
この問題が発生するリスクを軽減するには、インデックスを作成する前に次の手順を実行します。
コレクション内のドキュメントがどれもインデックス制約に違反していないことを検証します。
違反のない書き込み操作を保証できないアプリケーションからの、コレクションへの書き込みをすべて停止します。
最大同時インデックス構築数
デフォルトでは、サーバーは最大 3 つの同時インデックス構築を許可します。許可される同時インデックス構築の数を変更するには、 maxNumActiveUserIndexBuilds パラメータを変更します。
同時インデックス構築数が maxNumActiveUserIndexBuilds で指定された制限に達した場合、同時インデックス構築数が制限を下回るまで、サーバーは追加のインデックス構築をブロックします。
インデックス構築がデータベースのパフォーマンスに与える影響
書き込み負荷の高いワークロード中のインデックス構築
ターゲットコレクションの書き込み負荷が高いときにインデックスをビルドすると、書込みパフォーマンスが低下し、インデックスビルドに通常よりも時間がかかる場合があります。
こうした場合、アプリケーションでコレクションに対する書込み操作を停止または削減するメンテナンスウィンドウの指定を検討します。このメンテナンスウィンドウ中にインデックス構築を開始します。
使用可能なシステムメモリ (RAM) の不足
createIndexes は、コレクションでの 1 つ以上のインデックスの構築をサポートしています。createIndexes はメモリとディスク上の一時ファイルの組み合わせを使用してインデックスを構築します。デフォルトのメモリ制限は、createIndexes コマンドあたり 200 メガバイトで、そのコマンドでビルドされたすべてのインデックス間で均等に共有されます。例、1 つの createIndexes コマンドで 10 インデックスをビルドする場合、 MongoDB はデフォルトのメモリ制限である 200 を使用して、各インデックス20 メガバイトをインデックス構築プロセスに割り当てます。メモリ制限に達すると、 MongoDB はビルドを完了するために --dbpath 内の _tmp サブディレクトリに一時ファイルを作成します。
maxIndexBuildMemoryUsageMegabytes パラメーターを使用してメモリ制限を調整します。このパラメータを増やす必要があるのは、単一の createIndexes コマンドで多数の同時インデックス構築を実行する場合や、500 GBより大きいデータセットをインデックスする場合など、まれなケースのみです。
各 createIndexes コマンドには maxIndexBuildMemoryUsageMegabytes の制限があります。デフォルトの maxNumActiveUserIndexBuilds である 3 を使用する場合、すべての同時インデックスビルドの合計メモリ使用量は、maxIndexBuildMemoryUsageMegabytes の値の最大 3 倍に達します。
ホストマシンで使用可能な空き RAM が限られている場合は、 mongod RAM 使用量を変更する前に、メンテナンス期間をスケジュールしてシステム RAM の合計を増やす必要がある場合があります。
複製された環境でのインデックス構築
注意
FeatureCompatibilityVersion 4.4 以上が必要です。
レプリカセット全体でインデックス構築を同時に開始するには、レプリカセットまたはシャーディングされたクラスター内の各 mongod は、featureCompatibilityVersion を少なくとも 4.4 に設定する必要があります。
レプリカセットまたはシャーディングされたクラスター上のインデックスは、データを保持するすべてのレプリカセット ノードで同時に構築されます。シャーディングされたクラスターの場合、インデックス構築は、インデックスが作成されるコレクションのデータを含むシャードでのみ行われます。プライマリは、インデックスを使用可能とマークする前に、自身を含む最小限のデータを保持する voting ノード(コミットクォーラム)でインデックス構築を完了する必要があります。
ビルド プロセスの概要は以下の通りです。
プライマリは、
createIndexesコマンドを受信し、インデックス構築に関連付けられた "startIndexBuild" oplog エントリを直ちに作成します。セカンダリは、「startIndexBuild」oplog エントリを複製した後、インデックスの構築を開始します。
コレクション内のデータのインデックス作成が終了したら、各ノード間でビルドへのコミットについての ”投票” が行われます。
セカンダリノードは、プライマリが投票の定足数を確認するまで、引き続きインデックスへの新しい書込み操作を処理します。
プライマリで投票の定足数に達すると、重複キーエラーなどキーに関する制約違反がないかどうかがチェックされます。
キー制約違反がない場合、プライマリはインデックス構築を完了し、インデックスを使用準備完了としてマークし、関連する「commitIndexBuild」oplog エントリを作成します。
キー制約違反がある場合、インデックス構築は失敗します。プライマリはインデックス構築を中止し、関連する「abortIndexBuild」oplog エントリを作成します。
セカンダリは「commitIndexBuild」oplog エントリを複製し、インデックス構築を完了します。
セカンダリが代わりに「abortIndexBuild」oplog エントリを複製すると、インデックス構築を中止し、構築ジョブを破棄します。
シャーディングされたクラスターの場合、インデックス構築は、インデックスされるコレクションのデータを含むシャードでのみ行われます。
インデックス構築プロセスの詳細については、「 インデックス構築プロセス 」を参照してください。
デフォルトでは、インデックス構築は "votingMembers" のコミットクォーラム、つまりすべてのデータを保持する投票ノードを使用します。デフォルト以外のコミット クォーラムでインデックス構築を開始するには、 commitQuorumパラメータをcreateIndexesまたはそのシェルヘルパー db.collection.createIndex() および db.collection.createIndexes() に指定します。
進行中の同時インデックス構築に必要なコミットクォーラムを変更するには、setIndexCommitQuorum コマンドを使用します。
警告
ローリングインデックスと複製されたインデックス構築プロセスを同時に実行すると、ビルドの失敗やクラッシュ ループなどの予期しない問題が発生する可能性があるため、避けてください。
注意
コミットクォーラムと書込み保証の対比
インデックス構築にはコミットクォーラムを使用します。
書き込み操作には書込み保証が必要です。
クラスタ内の各データ保有ノードは投票ノードです。
コミットクォーラムでは、データを保持する投票ノードの数、またはプライマリがコミットを実行する前にプライマリを含めてどの投票ノードが同時インデックス ビルドのコミット準備をしておく必要があるかを指定します。
書込み保証 (write concern) とは、指定された数のインスタンスに書込み (write) が伝わったことを確認するレベルです。
コミットクォーラムでは、プライマリがインデックス構築にコミットする前に、インデックス構築を完了する準備が整っていなければならないノードの数を指定します。対照的に、プライマリがインデックス構築にコミットした時に、書込み保証によって、コマンドが返されるまでにインデックス構築を完了する必要があるノードの数が指定されます。
構築の失敗と復元
プライマリとセカンダリ で中断されたインデックス構築 mongod
mongodshutdown"force" : trueSIGTERMプライマリまたはセカンダリの votingMembersが を使用してクリーンな を実行するか、インデックス構築中に シグナルを受信し、 commitQuorum がデフォルトの に設定されている場合、インデックス構築の進行状況がディスクに保存されます。mongod は再起動時にインデックス構築を自動的に回復し、保存されたチェックポイントから続行します。以前のバージョンでは、インデックス構築を最初から再開する必要があります。
mongod は、インデックス構築をリカバリしていますながらスタートアッププロセスを実行できます。
mongodをスタンドアロンとして再起動した場合(つまり、 を削除するかコメントアウトするか、replication.replSetName --replSetNameを省略する)、mongod はインデックス構築を再開できません。手動でdropped になるまで、ビルドは一時停止状態のままになります。
スタンドアロンで中断されたインデックス構築 mongod
インデックスビルド中にmongodがシャットダウンすると、インデックスビルドジョブとすべての進行状況が失われます。 mongodを再起動しても、インデックスビルドは再開されません。 インデックスのビルドを再開するには、 createIndex()操作を再発行する必要があります。
ビルドプロセス中のロールバック
MongoDB 5.0以降では、インデックスビルド中にノードが以前の状態にロールバックされた場合、インデックスビルドの進行状況がディスクに保存されます。 ロールバックが完了したときに実行する作業がまだある場合、 mongodは自動的にインデックス構築を回復し、保存されたチェックポイントから続行します。
MongoDB では、進行中のインデックス構築を一時停止してロールバックを実行できます。
ロールバックしてもインデックス構築が取り消されない場合、MongoDB はロールバック完了後にインデックス構築を再開します。
ロールバックによってインデックス構築が取り消された場合は、ロールバックの完了後に 1 つまたは複数のインデックスを再作成する必要があります。
シャーディングされたコレクションのインデックスの整合性チェック
コレクションのチャンクを含む各シャードに完全に一致するインデックス(インデックスオプションを含む)が存在しない場合、シャーディングされたコレクションれたコレクションにはインデックスの一貫性がありません。通常の操作では一貫性のないインデックスは発生しないはずですが、次のシナリオでは一貫性のないインデックスが発生する可能性があります。
uniqueキー制約を使用してインデックスを作成し、1 つのシャードに重複ドキュメントを含むチャンクが含まれている場合。このような場合、インデックスの作成操作は、重複のないシャードでは成功するものの、重複のあるシャードでは成功しない可能性があります。複数のシャードにわたってインデックスをローリング処理で作成する場合(複数のシャードにわたって手作業でインデックスを 1 つずつビルドする場合)、関連付けられたシャードのインデックス作成に失敗するか、異なる仕様で誤ったインデックスをビルドする場合のいずれかになります。
コンフィギュレーションサーバーのプライマリは、シャーディングされたコレクションのシャード間でのインデックスの不整合を定期的にチェックします。 これらの定期的チェックを構成するには、 enableShardedIndexConsistencyCheckとshardedIndexConsistencyCheckIntervalMSを参照してください。
コマンドserverStatusは、構成サーバーのプライマリで実行された場合にインデックスの不整合を報告するフィールド shardedIndexConsistency を返します。
シャーディングされたコレクションに一貫性のないインデックスがないかどうかを確認するには、「シャード間で一貫性のないインデックスを検索する」を参照してください。
進行中のインデックス構築の監視
インデックス構築操作のステータスを確認するには、 のdb.currentOp() mongoshメソッドを使用できます。インデックス作成操作の現在の操作をフィルタリングする方法の例については、「アクティブなインデックス作成操作 」を参照してください。
msg フィールドには、インデックス構築プロセスの現在のステージにおける完了割合が含まれています。
インデックス構築の停止と再開をログで確認
インデックスが構築されている間、進捗状況は MongoDB ログに記録されます。インデックス構築が停止して再開されると、次のようなフィールドを含むログメッセージが表示されます。
"msg":"Index build: wrote resumable state to disk", "msg":"Found index from unfinished build",
進行中のインデックス構築の終了
進行中のインデックス構築を終了するには、 dropIndexes コマンドまたはそのシェルヘルパー dropIndex() または dropIndexes() を使用します。詳細については、「進行中のインデックス構築の停止」を参照してください。
レプリカセットまたはシャーディングされたクラスターで進行中のインデックス構築を終了するためにkillOp は使用しないでください。
インデックス構築のプロセス
次の表は、インデックス構築プロセスの各段階について説明しています。
ステージ | 説明 |
|---|---|
ロック |
|
初期化 |
|
ロック |
|
コレクションのスキャン | コレクション内の各ドキュメントに対して、 コレクションスキャン中に
|
プロセスサイド書込みテーブル |
|
投票とコミットクォーラムの待機 | レプリカセットの一部ではない
コミットクォーラムを待っている間、 |
ロック |
|
一時サイド書き込みテーブルの処理の完了 |
|
ロック |
|
サイド書き込みテーブルの削除 |
この時点で、インデックスにはコレクションに書き込まれたすべてのデータが含まれます。 |
プロセス制約違反テーブル |
|
インデックスを準備完了としてマークします |
|
ロック |
|