コレクションの再シャーディング
項目一覧
バージョン 5.0 で追加
理想的なシャードキーを使用すると、MongoDB は一般的なクエリ パターンにしながら、ドキュメントをクラスター全体に均等に分散できます。シャードキーが最適でないと、データ分散が不均等になるため、パフォーマンスやスケーリングの問題が発生する可能性があります。
MongoDB 5.0 以降では、コレクションの シャードキーを変更して 、クラスター全体のデータの分散を変更できます。
MongoDB 7.2 以降では、同じシャードキーでコレクションを 再シャーディング することができ、シャードキーを変更せずに新しいシャードを含めたり、別のゾーンにデータを再配布したりできます。
注意
コレクションを再シャーディングする前に、一般的なパフォーマンスとスケーリングの問題とその修正方法に関するアドバイスについては、 のシャードキーのトラブルシューティングをお読みください。
このタスクについて
一度にリシャーディングできるコレクションは 1 つだけです。
writeConcernMajorityJournalDefault
はtrue
である必要があります。一意の制約があるコレクションを再シャーディングするには、新しいシャードキーが既存の一意なインデックスの一意なインデックス要件を満たす必要があります。
次のコマンドと対応する shell メソッドは、再シャーディング操作の進行中に再シャーディングされるコレクションではサポートされていません。
リシャーディング操作の進行中、 クラスターでは以下のコマンドとメソッドはサポートされません。
警告
リシャーディング操作中に上記のコマンドのいずれかを使用すると、リシャーディング操作は失敗します。
再シャーディングするコレクションが Atlas Searchを使用する場合、再シャーディング操作の完了時に検索インデックスは使用できなくなります。 再シャーディング操作が完了してから、検索インデックスを手動で再構築する必要があります。
シャーディングされた時系列コレクションを再シャーディングすることはできません。
始める前に
コレクションを再シャーディングする前に、次の要件を満たしていることを確認してください。
アプリケーションは、影響を受けるコレクションが書込みをブロックする期間を2 秒許容できます。 書込み (write) がブロックされている期間中、アプリケーションのレイテンシが増加します。
ワークロードがこの要件を許容できない場合は、代わりにシャードキーの改良を検討してください。
データベースが次のリソース要件を満たしている。
コレクションを分散する各シャードで使用可能なストレージ領域が、再シャーディングするコレクションのサイズとその合計インデックスサイズの 2 倍以上であることを、シャードの数で割ったものであることを確認します。
storage_req = ( ( collection_storage_size + index_size ) * 2 ) / shard_count たとえば、 2 TB のデータを含み、4 つのシャードに分散された400 GB インデックスを持つコレクションを考えてみましょう。 このコレクションでリシャーディング操作を実行するには、各シャードに1.2が必要です TB の使用可能なストレージ。
1.2 TB storage = ( ( 2 TB collection + 0.4 TB index ) * 2 ) / 4 shards ストレージ要件を満たすには、再シャーディング操作中に 1 つ上のストレージ階層にアップグレードする必要がある場合があります。 操作が完了したらスケールダウンできます。
I/Oキャパシティーが50 % 未満であることを確認します。
CPU 負荷が80 % 未満であることを確認します。
重要
これらの要件はデータベースによって強制されません。 十分なリソースを割り当てられない場合、次の結果が発生する可能性があります。
データベースの容量が不足し、シャットダウンした
パフォーマンスの低下
操作に予想よりも時間がかかる
アプリケーションにトラフィックが少ない期間がある場合は、可能であれば、その時間中にコレクションに対してこの操作を実行します。
現在のシャードキーと新しいシャードキーの両方を使用するには、アプリケーションのクエリを書き直す必要があります。
Tip
アプリケーションがダウンタイムを許容できる場合は、現在のシャードキーと新しいシャードキーの両方を使用するようにアプリケーションのクエリを書き換えるのを避けるために、次の手順を実行します。
アプリケーションを停止します。
新しいシャードキーを使用するようにアプリケーションを書き換えます。
リシャーディングが完了するまで待ちます。 リシャーディング プロセスをモニターするには、
$currentOp
パイプライン ステージを使用します。書き換えたアプリケーションをデプロイします。
リシャーディングが完了する前に、クエリフィルターに現在のシャードキーまたは一意のフィールド(
_id
など)が含まれていない場合、次のクエリではエラーが返されます。最適なパフォーマンスを得るには、新しいシャードキーを含むように他のクエリも書き換えることをお勧めします。
再シャーディング操作が完了したら、クエリから古いシャードキーを削除できます。
インデックスのビルドは進行中ではありません。 実行中のインデックス ビルドを確認するには、
db.currentOp()
を使用します。db.adminCommand( { currentOp: true, $or: [ { op: "command", "command.createIndexes": { $exists: true } }, { op: "none", "msg" : /^Index Build/ } ] } ) 結果ドキュメントでは、
inprog
フィールド値が空の配列の場合、インデックスビルドは進行中ではありません。{ inprog: [], ok: 1, '$clusterTime': { ... }, operationTime: <timestamp> }
注意
リシャーディングは書き込み集中型のプロセスであり、oplog のレートが増加する可能性があります。 次のことをしたい場合があります。
固定の oplog サイズを設定して、oplog の無制限の増加を防ぎます。
oplog サイズを増やして 1 つ以上のセカンダリ ノードが古くなる可能性を最小限に抑えます。
詳細については、レプリカセットoplogのドキュメントを参照してください。
手順
コレクションの再シャーディング操作では、シャードは次のようになります。
ドナーは、シャーディングされたコレクションのチャンクを現在保存しています。
シャードは同時にドナーでも受信者でもあることができます。 ゾーン を使用する場合を除き、ドナー シャードのセットは受信者シャードと同じです。
コンフィギュレーションサーバーのプライマリは常にリシャーディング コーディネーターであり、リシャーディング操作の各フェーズを開始します。
リシャーディング操作を開始します。
mongos
に接続している間に、再シャーディングするコレクションと新しいシャードキーを指定するreshardCollection
コマンドを発行します。
db.adminCommand({ reshardCollection: "<database>.<collection>", key: <shardkey> })
MongoDB は、書込みをブロックする最大秒数を 2 秒に設定し、リシャーディング操作を開始します。
リシャーディング操作 を監視します。
リシャーディング操作をモニターするには、 $currentOp
パイプライン ステージを使用できます。
db.getSiblingDB("admin").aggregate([ { $currentOp: { allUsers: true, localOps: false } }, { $match: { type: "op", "originatingCommand.reshardCollection": "<database>.<collection>" } } ])
注意
更新された値を確認するには、前のパイプラインを継続的に実行する必要があります。
$currentOp
パイプラインの出力は次のとおりです。
totalOperationTimeElapsedSecs
: 経過したoptime (秒単位)remainingOperationTimeEstimatedSecs
: 現在のリシャーディング操作の推定残り時間(秒単位)。 新たにリシャーディング操作を開始すると、-1
として返されます。次以降:
MongoDB 5.0 および MongoDB 6.1 より前では、
remainingOperationTimeEstimatedSecs
は 再シャーディング操作 中に受信者シャードでのみ使用できます。MongoDB 6.1、
remainingOperationTimeEstimatedSecs
は、リシャーディング操作中にコーディネーターで使用することもできます。
リシャーディング操作では、これらのフェーズを順番に実行されます。
クローン フェーズは、現在のコレクション データを複製します。
キャッチアップ フェーズは、保留中の書込み (write) 操作をリシャーディングされたコレクションに適用します。
remainingOperationTimeEstimatedSecs
は悲観的な時間推定値に設定されています。キャッチアップフェーズの推定時間は、比較的長い時間であるクローンフェーズ時間に設定されます。
実際には、保留中の書込み操作が少ない場合、実際のキャッチアップ フェーズ時間は比較的短いです。
[ { shard: '<shard>', type: 'op', desc: 'ReshardingRecipientService | ReshardingDonorService | ReshardingCoordinatorService <reshardingUUID>', op: 'command', ns: '<database>.<collection>', originatingCommand: { reshardCollection: '<database>.<collection>', key: <shardkey>, unique: <boolean>, collation: { locale: 'simple' } }, totalOperationTimeElapsedSecs: <number>, remainingOperationTimeEstimatedSecs: <number>, ... }, ... ]
リシャーディング操作を完了します。
リシャーディング プロセス全体では、リシャーディング操作を完了するための推定時間( remainingOperationTimeEstimatedSecs
)が減少します。 推定時間が2 秒未満の場合、MongoDB は書込みをブロックし、リシャーディング操作を完了します。 リシャーディング操作の完了までの推定時間が 2 秒を下回るまで、リシャーディング操作はデフォルトで書込みをブロックしません。 書込み (write) がブロックされている期間中、アプリケーションのレイテンシが増加します。
リシャーディング プロセスが完了すると、リシャーディング コマンドはok: 1
を返します。
{ ok: 1, '$clusterTime': { clusterTime: <timestamp>, signature: { hash: Binary(Buffer.from("0000000000000000000000000000000000000000", "hex"), 0), keyId: <number> } }, operationTime: <timestamp> }
リシャーディング操作が正常に完了したかどうかを確認するには、 sh.status()
メソッドの出力を確認します。
sh.status()
sh.status()
メソッドの出力にはdatabases
のサブセクションが含まれています。 リシャーディングが正常に完了すると、出力にはコレクションの新しいシャードキーが一覧表示されます。
databases [ { database: { _id: '<database>', primary: '<shard>', version: { uuid: <uuid>, timestamp: <timestamp>, lastMod: <number> } }, collections: { '<database>.<collection>': { shardKey: <shardkey>, unique: <boolean>, balancing: <boolean>, chunks: [], tags: [] } } } ... ]
注意
リシャーディングされたコレクションでAtlas Searchが使用される場合、リシャーディング操作の完了時に検索インデックスは使用できなくなります。 再シャーディング操作が完了してから、検索インデックスを手動で再構築する必要があります。
再シャーディングを強制的に完了させるために、早期に書込みをブロックします
commitReshardCollection
コマンドを発行すると、リシャーディング操作を手動で強制的に完了できます。 これは、再シャーディング操作を完了するための現在の推定時間がコレクションで書込みをブロックする許容期間である場合に有用です。 commitReshardCollection
コマンドは、クリティカル セクションの期間書込みをブロックし、リシャーディング操作を強制的に完了させます。 このコマンドの構文は、次のとおりです。
db.adminCommand({ commitReshardCollection: "<database>.<collection>" })
リシャーディング操作の中止
リシャーディング操作の任意の段階で、 commitReshardCollection
を実行した後でも、シャードが完全に追いつくまで、リシャーディング操作を中止できます。
たとえば、 remainingOperationTimeEstimatedSecs
が減少しない場合は、 abortReshardCollection
コマンドを使用してリシャーディング操作を中止できます。
db.adminCommand({ abortReshardCollection: "<database>.<collection>" })
操作をキャンセルした後、書込み量が少ない時間枠でリシャーディング操作を再試行できます。 これが不可能な場合は、再試行する前にシャードを追加してください。
動作
リシャーディング操作の最小期間
リシャーディング操作の最小期間は常に 5 分です。
再試行可能な書き込み
リシャーディング前または再シャーディング中に開始された再試行可能な書込みは、コレクションが最大 5 分間再シャーディングされた期間中に、および再シャーディングされた後に再試行できます。 5 分後、書き込みの決定的な結果が見つからず、その後書き込みを再試行しようとすると失敗し、 IncompleteTransactionHistory
エラーが発生します。
エラーケース
Duplicate _id
Values
コレクション データの破損を避けるために、 _id
の値がグローバルに一意でない場合、リシャーディング操作は失敗します。 _id
の値が重複していると、チャンク移行が成功し ない 可能性もあります。 _id
値が重複しているドキュメントがある場合は、それぞれから新しいドキュメントにデータをコピーしてから、重複するドキュメントを削除します。