Docs Menu
Docs Home
/
MongoDBマニュアル
/

データが存在するコレクションでのインデックス構築

項目一覧

  • 動作
  • インデックス構築がデータベースのパフォーマンスに与える影響
  • 複製された環境でのインデックス構築
  • 構築の失敗と復元
  • 進行中のインデックス構築の監視
  • 進行中のインデックス構築の終了
  • インデックス構築のプロセス

インデックス構築では、最適化された構築プロセスを使用し、インデックス構築の開始時と終了時にコレクションを排他ロックします。構築プロセスの残りの部分は、読み取り操作と書き込み (write) 操作のインターリーブによって一時停止されます。インデックス構築プロセスとロック動作の詳細については、インデックス構築プロセス」を参照してください。

レプリカセットまたはシャーディングされたクラスター上のインデックスは、データを保持する全レプリカセット ノードで同時に構築されます。プライマリでは、最小数のデータを保持する投票ノード(コミットクォーラム)が必要です。これにはプライマリ自身も含まれます。また、インデックスが使用可能とマークされる前に構築を完了する必要があります。「投票」ノードとは、members[n].votes0 より大きいレプリカセットのノードです。詳細については、 「レプリケートされた環境でのインデックス構築」を参照してください。

注意

Atlas でのインデックス作成の詳細については、Atlas ドキュメントの「インデックス管理ページ 」を参照してください。

MongoDB の以前のバージョンでは、フォアグラウンドまたはバックグラウンドでのインデックスの構築がサポートされていました。フォアグラウンドでのインデックス構築は高速で、より効率の高いインデックスデータ構造が生成されていましたが、構築中はインデックスされるコレクションの親データベースへの読取りおよび書込みアクセスをすべてブロックする必要がありました。バックグラウンドでのインデックス構築は遅く、結果の効率も低いものでしたが、構築プロセス中にデータベースとそのコレクションへの読取りおよび書込みアクセスが可能でした。

インデックス構築では、メタデータの変更を保護するために、構築プロセスの開始時と終了時に、インデックスが作成されるコレクションのみが排他ロックされるようになりました。構築プロセスの残りの部分では、バックグラウンド インデックス構築の一時停止動作を使用して、構築中のコレクションへの読み取り/書込みアクセスを最大化しています。インデックス構築では、ロック動作の制限が緩いにもかかわらず、効率的なインデックス データ構造が生成されます。

最適化されたインデックス構築のパフォーマンスは、最低でもバックグラウンド インデックス構築と同等です。構築プロセス中に更新がほとんどまたはまったく受信されないワークロードの場合、最適化されたインデックス構築は、同じデータに対するフォアグラウンド インデックス構築と同じくらい高速になります。

進行中のインデックス構築の進行状況を監視するには、db.currentOp() を使用します。

MongoDB では、createIndexesまたはそのシェルヘルパーcreateIndex()createIndexes()に指定されている場合は background インデックス構築は無視されます。

一意のインデックスなど、コレクションに制約を強制するインデックスの場合、 mongodはインデックスのビルド完了後に、既存のドキュメントと同時に書込まれたすべてのドキュメントをチェックし、それらの制約に違反しているかどうかをチェックします。 インデックス制約に違反するドキュメントは、インデックスのビルド中に存在する可能性があります。 ビルドの最後にインデックス制約に違反するドキュメントがある場合、 mongodはビルドを終了し、エラーをスローします。

たとえば、データが入ったコレクションinventoryを考えてみましょう。 管理者が、 product_skuフィールドに一意のインデックスを作成したいと考えています。 コレクション内のいずれかのドキュメントでproduct_skuの値が重複している場合でも、インデックスのビルドは正常に開始できます。 ビルドの最後に違反がまだ存在する場合、 mongodはビルドを終了し、エラーをスローします。

同様に、インデックスのビルドが進行中に、アプリケーションはproduct_skuの重複する値を持つドキュメントをinventoryコレクションに正常に書き込むことができます。 ビルドの最後に違反がまだ存在する場合、 mongodはビルドを終了し、エラーをスローします。

制約違反によるインデックス構築失敗のリスクを軽減するには、以下の対策を取ります。

  • コレクション内のドキュメントがどれもインデックス制約に違反していないことを検証します。

  • 違反のない書き込み操作を保証できないアプリケーションからの、コレクションへの書き込みをすべて停止します。

複数のシャードに分散されたシャーディングされたコレクションの場合、1 つ以上のシャードに重複したドキュメントを含むチャンクが含まれる場合があります。そのため、インデックスの作成操作は、一部のシャード(重複のないシャード)では成功するものの、他のシャード(重複のあるシャード)では成功しない場合があります。シャード間で不整合なインデックスが残らないようにするには、mongos から db.collection.dropIndex() を発行して、コレクションからインデックスを削除します。

この問題が発生するリスクを軽減するには、インデックスを作成する前に次の手順を実行します。

  • コレクション内のドキュメントがどれもインデックス制約に違反していないことを検証します。

  • 違反のない書き込み操作を保証できないアプリケーションからの、コレクションへの書き込みをすべて停止します。

Tip

以下も参照してください。

デフォルトでは、サーバーは最大 3 つの同時インデックス構築を許可します。許可される同時インデックス構築の数を変更するには、 maxNumActiveUserIndexBuilds パラメータを変更します。

同時インデックス構築数が maxNumActiveUserIndexBuilds で指定された制限に達した場合、同時インデックス構築数が制限を下回るまで、サーバーは追加のインデックス構築をブロックします。

ターゲットとなるコレクションの書き込み負荷が大きい時間帯にインデックスを構築すると、書き込みパフォーマンスが低下し、インデックス構築に時間がかかる可能性があります。

アプリケーションがコレクションに対する書き込み操作を停止または削減するメンテナンスウィンドウを指定することを検討してください。このメンテナンスウィンドウ中にインデックス構築を開始することで、構築プロセスの潜在的な負の影響を軽減します。

createIndexesは、コレクションに 1 つ以上のインデックスの構築をサポートしています。 createIndexesはメモリとディスク上の一時ファイルの組み合わせを使用してインデックス構築を完了します。 createIndexesのメモリ使用量のデフォルト制限は200メガバイトで、単一のcreateIndexesコマンドを使用してビルドされたすべてのインデックスに共有されます。 メモリ制限に達すると、 createIndexes--dbpathディレクトリ内の_tmpという名前のサブディレクトリにある一時ディスク ファイルを使用してビルドを完了します。

maxIndexBuildMemoryUsageMegabytesサーバー パラメータを設定することで、メモリ制限を上書きできます。メモリ制限を高く設定すると、より早くインデックス構築を完了できる可能性があります。ただし、システム上の未使用 RAM に対してこの制限を高く設定しすぎると、メモリが不足し、サーバーがシャットダウンする可能性があります。

ホストマシンで使用可能な空き RAM が限られている場合は、 mongod RAM 使用量を変更する前に、メンテナンス期間をスケジュールしてシステム RAM の合計を増やす必要がある場合があります。

注意

FeatureCompatibilityVersion 4.4 以上が必要です。

レプリカセット全体でインデックス構築を同時に開始するには、レプリカセットまたはシャーディングされたクラスター内の各 mongod は、featureCompatibilityVersion を少なくとも 4.4 に設定する必要があります

レプリカセットまたはシャーディングされたクラスター上のインデックスは、データを保持するすべてのレプリカセット ノードで同時に構築されます。シャーディングされたクラスターの場合、インデックス構築は、インデックスが作成されるコレクションのデータを含むシャードでのみ行われます。プライマリは、インデックスを使用可能とマークする前に、自身を含む最小限のデータを保持する voting ノード(コミットクォーラム)でインデックス構築を完了する必要があります。

ビルド プロセスの概要は以下の通りです。

  1. プライマリは、createIndexes コマンドを受信し、インデックス構築に関連付けられた "startIndexBuild" oplog エントリを直ちに作成します。

  2. セカンダリは、「startIndexBuild」oplog エントリを複製した後、インデックスの構築を開始します。

  3. コレクション内のデータのインデックス作成が終了したら、各ノード間でビルドへのコミットについての ”投票” が行われます。

  4. セカンダリノードは、プライマリが投票の定足数を確認するまで、引き続きインデックスへの新しい書込み操作を処理します。

  5. プライマリで投票の定足数に達すると、重複キーエラーなどキーに関する制約違反がないかどうかがチェックされます。

    • キー制約違反がない場合、プライマリはインデックス構築を完了し、インデックスを使用準備完了としてマークし、関連する「commitIndexBuild」oplog エントリを作成します。

    • キー制約違反がある場合、インデックス構築は失敗します。プライマリはインデックス構築を中止し、関連する「abortIndexBuild」oplog エントリを作成します。

  6. セカンダリは「commitIndexBuild」oplog エントリを複製し、インデックス構築を完了します。

    セカンダリが代わりに「abortIndexBuild」oplog エントリを複製すると、インデックス構築を中止し、構築ジョブを破棄します。

シャーディングされたクラスターの場合、インデックス構築は、インデックスされるコレクションのデータを含むシャードでのみ行われます。

インデックス構築プロセスの詳細については、「 インデックス構築プロセス 」を参照してください

デフォルトでは、インデックス構築は "votingMembers" のコミットクォーラム、つまりすべてのデータを保持する投票ノードを使用します。デフォルト以外のコミット クォーラムでインデックス構築を開始するには、 commitQuorumパラメータをcreateIndexesまたはそのシェルヘルパー db.collection.createIndex() および db.collection.createIndexes() に指定します。

進行中の同時インデックス構築に必要なコミットクォーラムを変更するには、setIndexCommitQuorum コマンドを使用します。

注意

インデックス構築はレプリカセットのパフォーマンスに影響を与える可能性があります。インデックス構築によるパフォーマンスの低下を許容できないワークロードの場合は、ローリングインデックス構築プロセスの実行を検討してください。ローリングインデックス構築では、一度に最大 1 つのレプリカセットノードを使用し、セカンダリノードから始めて、そのノードにスタンドアロンとしてインデックスを構築します。ローリングインデックス構築には、少なくとも 1 回のレプリカセット選挙が必要です。

コミットクォーラム書込み保証には重要な違いがあります。

  • インデックス構築にはコミットクォーラムを使用します。

  • 書き込み操作には書込み保証が必要です

クラスタ内の各データ保有ノードは投票ノードです。

コミットクォーラムでは、データを保持する投票ノードの数、またはプライマリがコミットを実行する前にプライマリを含めてどの投票ノードが同時インデックス ビルドのコミット準備をしておく必要があるかを指定します。

書込み保証 (write concern) とは、指定された数のインスタンスに書込み (write) が伝わったことを確認するレベルです。

コミットクォーラムでは、プライマリがインデックス構築にコミットする前に、インデックス構築を完了する準備が整っていなければならないノードの数を指定します。対照的に、プライマリがインデックス構築にコミットした時に、書込み保証によって、コマンドが返されるまでにインデックス構築を完了する必要があるノードの数が指定されます。

MongoDB 5.0以降では、プライマリmongod"force" : trueを使用してクリーンなshutdownを実行するか、インデックス構築中にSIGTERMシグナルを受信し、 commitQuorumがデフォルトのvotingMembersに設定されている場合、インデックス構築進行状況はディスクに保存されます。 mongodは再起動時に自動的にインデックス構築を回復し、保存されたチェックポイントから続行します。 以前のバージョンでは、インデックスの構築が中断された場合、最初からやり直す必要がありました。

MongoDB 5.0以降では、セカンダリ mongod"force" : true を使用してクリーン shutdown を実行するか、インデックス構築中に SIGTERM シグナルを受信し、commitQuorum がデフォルトの votingMembers に設定されている場合、インデックス構築の進行状況がディスクに保存されます。mongod は、再起動時にインデックス構築を自動的に回復し、保存されたチェックポイントから続行します。以前のバージョンでは、インデックス構築が中断された場合、最初からやり直す必要がありました。

mongodは、リカバリ インデックスの構築中にスタートアッププロセスを実行できます。

mongodをスタンドアロン( replication.replSetNameを削除またはコメントアウトするか、 --replSetNameを省略すると、 mongodはインデックスビルドを再開できなくなります。 手動でdroppedになるまで、ビルドは一時停止状態のままになります。

インデックスビルド中にmongodがシャットダウンすると、インデックスビルドジョブとすべての進行状況が失われます。 mongodを再起動しても、インデックスビルドは再開されません。 インデックスのビルドを再開するには、 createIndex()操作を再発行する必要があります。

MongoDB 5.0以降では、インデックスビルド中にノードが以前の状態にロールバックされた場合、インデックスビルドの進行状況がディスクに保存されます。 ロールバックが完了したときに実行する作業がまだある場合、 mongodは自動的にインデックス構築を回復し、保存されたチェックポイントから続行します。

MongoDB では、進行中のインデックス構築を一時停止してロールバックを実行できます。

  • ロールバックしてもインデックス構築が取り消されない場合、MongoDB はロールバック完了後にインデックス構築を再開します。

  • ロールバックによってインデックス構築が取り消された場合は、ロールバックの完了後に 1 つまたは複数のインデックスを再作成する必要があります。

コレクションのチャンクを含む各シャードにまったく同じインデックス(インデックスオプションを含む)がない場合、シャーディングされたコレクションのインデックスには一貫性がありません。通常の操作では一貫性のないインデックスは発生しないはずですが、次のような一貫性のないインデックスが発生する可能性があります。

  • ユーザーが unique キー制約を使用してインデックスを作成していて、1 つのシャードに重複ドキュメントを含むチャンクが含まれている場合。このような場合、インデックスの作成操作は、重複のないシャードでは成功するものの、重複のあるシャードでは成功しない可能性があります。

  • ユーザーが複数のシャードにわたってインデックスをローリング処理で作成している(複数のシャードにわたって手作業でインデックスを 1 つずつ構築している)時、関連付けられたシャードのインデックス作成に失敗した場合、または異なる仕様で誤ったインデックスを構築した場合。

コンフィギュレーションサーバーのプライマリは、シャーディングされたコレクションのシャード間でのインデックスの不整合を定期的にチェックします。 これらの定期的チェックを構成するには、 enableShardedIndexConsistencyCheckshardedIndexConsistencyCheckIntervalMSを参照してください。

コマンド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 は使用しないでください。

次の表は、インデックス構築プロセスの各段階について説明しています。

ステージ
説明

ロック

mongodは、インデックス作成されるコレクションに対して排他Xロックを取得します。 これにより、コレクションを対象とする複製された書込み (write) 操作やメタデータ コマンドの適用など、コレクションに対するすべての読み取り操作と書込み (write) 操作がブロックされます。 The mongod does not yield this lock.

初期化

mongodは、この初期状態で次の 3 つのデータ構造を作成します。

  • 初期インデックスのメタデータエントリ。

  • ビルドプロセス中にインデックスされるコレクションへの書込みによって生成されたキーを格納する一時テーブル (サイド書込みテーブル)。

  • キー生成エラーを引き起こす可能性のあるすべてのドキュメントの一時テーブル (制約違反テーブル)。ドキュメントのインデックス フィールドに無効なキーがある場合、キー生成エラーが発生します。たとえば、ユニークインデックスを構築するときにフィールド値が重複しているドキュメント、または 2dsphere インデックスを構築するときに GeoJSON オブジェクト が不正な場合などです。

ロック

mongodは、排他的X IXロックを意向排他 ロックにダウングレードします。 mongodは、読み取り操作と書込み(write)操作をインターリーブするためにこのロックを定期的にロックします。

コレクションのスキャン

コレクション内の各ドキュメントに対して、 mongodはそのドキュメントのキーを生成し、そのキーを外部ソーターにダンプします。

コレクションスキャン中にmongodがキーを生成中にキー生成エラーが発生した場合、後で処理できるように制約違反テーブルに保存されます。

mongodがキーの生成中に他のエラーに発生した場合、ビルドはエラーで失敗します。

mongodがコレクションスキャンを完了すると、ソートされたキーをインデックスにダンプします。

プロセスサイド書込みテーブル

mongodは、先入れ先出しの優先順位を使用してサイド書き込みテーブルを空にします。

mongodがサイド書込みテーブルでキーを処理中にキー生成エラーを発生した場合、後で処理できるように制約違反テーブルに保存されます。

mongodがキーを処理中に他のエラーが発生した場合、ビルドはエラーで失敗します。

mongod は、構築プロセス中にコレクションに書き込まれるドキュメントごとに、そのドキュメントのキーを生成し、後で処理できるようにサイド書込みテーブルに格納します。mongod はスナップショット システムを使用して、処理するキーの数に制限を設定します。

投票とコミットクォーラムの待機

レプリカセットの一部ではないmongodは、このステージをスキップします。

mongodは、インデックスをコミットするためにプライマリに「投票」を送信します。 具体的には、プライマリ上の内部複製コレクションに「投票」を書込みます。

mongodプライマリの場合、コミットクォーラムが投票(デフォルトではすべての投票データを保持するノード)に達するまで待機してから、インデックス ビルド プロセスを続行します。

mongodセカンダリの場合、"commitIndexBuild" または "abortIndexBuild" oplog エントリのいずれかが複製されるまで待機します。

  • mongodが "CommitIndexBuild" oplog エントリを複製すると、サイド書込みテーブルの処理が完了し、インデックス構築プロセスの次の段階に進みます。

  • mongod が "abortIndexBuild" oplog エントリを複製すると、インデックス構築が中止され、構築ジョブが破棄されます。

コミットクォーラムを待っている間、mongod は、インデックス付けされるコレクションへの書込み (write) 操作から生成された追加のキーをサイド書込みテーブルに追加し、定期的にテーブルを空にします。

ロック

mongodは、コレクションの意向排他IXロックを共有Sロックにアップグレードします。 これにより、コレクションを対象とする複製された書込み (write) 操作やメタデータ コマンドの適用など、コレクションへのすべての書込み (write) 操作がブロックされます。

一時サイド書き込みテーブルの処理の完了

mongod は、一時テーブル内の残りのレコードの処理を続行します。mongod はこの段階でレプリケーションを一時停止する可能性があります。

mongodがサイド書込みテーブルでキーを処理中にキー生成エラーを発生した場合、後で処理できるように制約違反テーブルに保存されます。

mongodがキーを処理中に他のエラーが発生した場合、ビルドはエラーで失敗します。

ロック

mongod は、コレクションの共有 S ロックをコレクションの排他的 X ロックにアップグレードします。これにより、コレクションを対象とする複製された書込み (write) 操作やメタデータ コマンドの適用など、コレクションに対するすべての読み取り操作と書込み (write) 操作がブロックされます。mongod はこのロックを停止しません。

サイド書き込みテーブルの削除

mongodは、削除する前にサイド書込みテーブル内の残りの操作を適用します。

mongodがサイド書込みテーブルでキーを処理中にキー生成エラーを発生した場合、後で処理できるように制約違反テーブルに保存されます。

mongodがキーを処理中に他のエラーが発生した場合、ビルドはエラーで失敗します。

この時点で、インデックスにはコレクションに書き込まれたすべてのデータが含まれます。

プロセス制約違反テーブル

mongodプライマリの場合、先入れ先出しの優先順位を使用して制約違反テーブルを空にします。

  • 制約違反テーブルのどのキーもキー生成エラーを生成しない場合、またはテーブルが空の場合、 mongodはテーブルを削除し、"commitIndexBuild" oplog エントリを作成します。 セカンダリは、oplog エントリを複製した後、関連するインデックスのビルドを完了できます。

  • 制約違反テーブル内のいずれかのキーでもキー生成エラーが発生する場合、 mongodはビルドを中止し、エラーをスローします。 mongodは、関連する "abortIndexBuild" oplog エントリを作成し、セカンダリがインデックス構築ジョブを中止して破棄する必要があることを示します。

mongodセカンダリの場合、制約違反テーブルが削除されます。 "commitOplogEntry" oplog エントリを作成する前に、プライマリが制約違反テーブルを正常に空にする必要があるため、セカンダリは違反が存在しないことを前提とできます。

インデックスを準備完了としてマークします

mongodはインデックスを使用可能としてマークするようにインデックス メタデータを更新します。

ロック

mongodはコレクションのXロックを解放します。

Tip

以下も参照してください。

戻る

一意への変換