データの挿入、更新、削除によって時間の経過とともにディスクフラグメントが生成されます。compact コマンドを使用すると、プライマリノードとセカンダリノードからこれらのフラグメントを回収し、ディスク使用率を向上させることができます。
ディスクフラグメントを回収するには、ストレージ分析機能の使用を推奨します。この機能はより簡単で、サービスへの影響も少ないです。ストレージ分析は、非表示ノードからのみフラグメントを回収します。プライマリノードとセカンダリノードからフラグメントを回収するには、まずプライマリ/セカンダリフェイルオーバーを実行してください。
ストレージ分析は、以下の MongoDB バージョンで利用できます。
-
MongoDB 8.0:すべてのマイナーバージョン。
-
MongoDB 7.0:すべてのマイナーバージョン。
-
MongoDB 6.0:すべてのマイナーバージョン。
-
MongoDB 5.0:すべてのマイナーバージョン。
-
MongoDB 4.4:4.4.7 以降。
-
MongoDB 4.2:4.2.23 以降。
前提条件
インスタンスが WiredTiger ストレージエンジンを使用している必要があります。
注意事項
-
データのバックアップ:フラグメントを回収する前に、データベースをバックアップしてください。
-
compactコマンドの影響:compactコマンドは、コレクション内のすべてのデータとインデックスを再書き込みしてデフラグすることで、未使用の領域を回収します。-
読み取り/書き込みのブロックとパフォーマンスへの影響
-
MongoDB 4.4 より前のバージョンでは、
compactコマンドはデータベースをロックし、すべての読み取りおよび書き込み操作をブロックします。断片化が激しいコレクションでは、compactコマンドの実行に時間がかかり、非表示ノードでのレプリケーションのレイテンシーが増加する可能性があります。フラグメントを再利用する前に、この操作をオフピーク時間に実行するか、oplog サイズを増やすか、または MongoDB 4.4 以降にメジャーバージョンをアップグレードしてください。 -
MongoDB 4.4 以降では、
compactコマンドは読み取りおよび書き込み操作をブロックしませんが、パフォーマンスに影響を与える可能性があります。この操作はオフピーク時間に実行してください。
-
-
ノードの再構築
-
MongoDB 3.4、4.0、4.2 (4.0.22 以前)、または 4.4 (5.0.6 以前) では、
compactを実行しているノードは [RECOVERING] 状態になります。この操作に時間がかかりすぎると、ヘルスチェックによってノードが異常であると見なされ、[ノードの再構築] がトリガーされる可能性があります。詳細については、「MongoDB マイナーバージョンのリリースノート」をご参照ください。 -
後の MongoDB バージョンでは、
compactを実行しているノードは SECONDARY 状態のままになり、ノードの再構築をトリガーしません。
-
-
-
効果のない
compactコマンド:compactコマンドは、次のシナリオでは効果がない場合があります (block_compact):-
コレクションの物理ストレージサイズが 1 MB 未満の場合。
-
断片化率が 20% 未満の場合。
-
データファイルの最初の 80% に 20% 未満の空き領域が存在する場合、またはデータファイルの最初の 90% に 10% 未満の空き領域が存在する場合。
-
-
回収時間:
compactの実行時間は、データ量とシステム負荷によって異なります。 -
その他の注意事項:
-
compactによって解放された領域は、合計空き領域よりも少なくなる場合があります。新しい操作を開始する前に、前のcompact操作が完了していることを確認してください。 -
ディスク領域がフルになってインスタンスがロックされた場合でも、
compactコマンドは実行できます。
-
背景情報
ディスクフラグメントが発生する理由
-
発生メカニズム:データが削除されると、ストレージ領域は空きとしてマークされます。新しいデータはこの領域を再利用するか、ファイルの末尾に追加されます。これにより、未使用の領域が断片的に生成され、これがディスクフラグメントとなります。
-
影響:フラグメントが多いほど、実効ディスク使用率は低下します。たとえば、100 GB のディスクに 20 GB のフラグメントと 60 GB のアクティブデータがある場合、報告される使用率は 80% (80 GB/100 GB) ですが、実効使用率は 60% (60 GB/100 GB) にすぎません。
ディスクフラグメントを回収するタイミング
-
大量のデータを削除した後
大量のドキュメントを削除すると、解放された領域はオペレーティングシステムに返されず、将来の書き込みのために予約されます。これにより、ディスク上に大量の断片化された領域が残る可能性があります。
重要手動削除も TTL による期限切れも、ディスクフラグメントを自動的に回収しません。領域を手動で回収する必要があります。
-
長時間の高負荷書き込みワークロードの後
持続的な高負荷書き込みワークロード (頻繁な挿入、更新、削除) により、ディスク全体に断片化された領域が徐々に蓄積されます。
-
ディスク容量が少なく、断片化が 20% を超える場合
ディスク使用率が 85% から 90% 以上に達した場合、フラグメントを回収することで領域を解放し、ストレージの逼迫を軽減できます。
ディスク領域の確認
コレクションのストレージ状態の確認
db.runCommand({collStats: <collection_name>}) コマンドを実行してストレージステータスを表示します。主要な出力フィールド:
-
size:コレクションの論理ストレージサイズです。 -
storageSize: コレクションの物理ストレージサイズです。 -
freeStorageSize:コレクション内の再利用可能な空き領域です。MongoDB 4.4 以降で利用可能です。
remove コマンドでドキュメントを削除した後、size は減少しますが、storageSize は減少しない場合があります。freeStorageSize の storageSize に対する比率が高いことは、フラグメンテーションが高いことを示します。
これらのフィールド (size、storageSize、freeStorageSize) は collStats-Output に記載されています。
回収可能な領域の見積もり
-
mongo shell を使用して ApsaraDB for MongoDB インスタンスに接続します。レプリカセットインスタンスの場合は、サービスへの影響を最小限に抑えるために、セカンダリノードに接続してください。接続手順:
-
コレクションを含むデータベースに切り替えます。
構文:
use <database_name>パラメーターの説明:
<database_name>は、コレクションを含むデータベースの名前です。説明show dbsコマンドを実行すると、既存のデータベースを照会できます。例:
test_database データベースに切り替えます。
use test_database -
コレクションで回収可能なディスクフラグメントの量を確認します。
構文:
db.<collection_name>.stats().wiredTiger["block-manager"]["file bytes available for reuse"]パラメーターの説明:
<collection_name>はコレクションの名前です。説明show tablesコマンドを実行すると、既存のコレクションをクエリできます。例:
db.test_database_collection.stats().wiredTiger["block-manager"]["file bytes available for reuse"]次の結果が返されます。
207806464この出力は、回収可能と推定される領域が 207,806,464 バイトであることを示します。
ディスクフラグメントの回収
スタンドアロンまたはレプリカセットインスタンス
-
スタンドアロンインスタンスは、単一のノードで構成されています。それに接続して
compactコマンドを実行し、ディスクのフラグメントを回収します。 -
レプリカセットインスタンスは複数のノードで構成されます。プライマリノードとセカンダリノードの両方からフラグメントを回収します。
重要-
サービスへの影響を最小限に抑えるには、まずセカンダリノードからフラグメントを回収します。次に、プライマリ/セカンダリフェイルオーバーを実行し、元のプライマリノード (現在はセカンダリ) からフラグメントを回収します。
-
レプリカセットインスタンスに読み取り専用ノードがある場合は、それらのディスクフラグメントも回収してください。コマンドは、プライマリノードおよびセカンダリノードと同じです。
-
-
mongo shell を使用してインスタンスに接続します。接続手順:
-
コレクションを含むデータベースに切り替えます。
構文:
use <database_name>パラメーター
<database_name>は、コレクションを含むデータベースの名前です。説明show dbsコマンドを実行すると、既存のデータベースを照会できます。例:
replica_database データベースに切り替えます。
use replica_database -
ディスクフラグメントを回収する前に、データベースが占有しているディスク領域を確認します。
db.stats()説明このコマンドは、変更せずにコピーして実行できます。
-
コレクションからディスクフラグメントを回収します。
構文:
db.runCommand({compact:"<collection_name>",force:true})パラメータ:
-
<collection_name>: コレクションの名前です。説明show tablesコマンドを実行して、既存のコレクションを照会できます。 -
force: 任意。値はtrueである必要があります。このパラメータは、バージョン 4.2 以前を実行している ApsaraDB for MongoDB インスタンスのプライマリノードでこのコマンドを実行する場合に必要です。
例:
db.runCommand({compact:"sharded_collection"})操作が成功すると、次の結果が返されます。
{ "ok" : 1 } -
-
ディスクフラグメントを回収した後、データベースが占有しているディスク領域を確認します。
db.stats()説明このコマンドは、変更せずにコピーして実行できます。
シャードクラスターインスタンス
シャードクラスターインスタンスの場合、シャードノードからのみディスクフラグメントを回収します。mongos および config server コンポーネントはユーザーデータを保存しないため、これらのフラグメントを回収する必要はありません。
シャードクラスターインスタンスの読み取り専用ノードでは、compact コマンドはサポートされていません。
-
mongo shell を使用してシャードクラスターインスタンスに接続します。mongo shell を使用したシャードクラスターインスタンスへの接続をご参照ください。
-
コレクションを含むデータベースに切り替えます。
構文:
use <database_name>パラメーターの説明:
<database_name>は、コレクションを含むデータベースの名前です。説明show dbsコマンドを実行して、既存のデータベースを照会できます。例:
sharded_database データベースに切り替えます。
use sharded_database -
ディスクフラグメントを回収する前に、データベースが占有しているディスク領域を確認します。
db.stats()説明このコマンドは、変更せずにコピーして実行できます。
-
コレクションからディスクフラグメントを回収します。
各シャード内のプライマリノードとセカンダリノードの両方からフラグメントを回収します。
重要サービスへの影響を最小限に抑えるには、まずセカンダリノードからフラグメントを回収します。次に、プライマリ/セカンダリフェイルオーバーを実行し、元のプライマリノード (現在はセカンダリ) からフラグメントを回収します。
-
シャードコンポーネント内のセカンダリノードからディスクフラグメントを回収します。
コマンドは、mongo shell と mongosh で異なります。お使いのクライアントに対応するタブを選択してください。
説明Mongosh 2.x では、mongosh 1.x とは異なり、リードプリファレンスを指定するパラメータが追加されています。
Mongo shell
構文:
db.runCommand({runCommandOnShard:"<Shard ID>","command":{compact:"<collection_name>"},$queryOptions: {$readPreference: {mode: 'secondary'}}})パラメータ:
-
<Shard ID>: シャードコンポーネントの ID。説明MongoDB コンソールにログインします。対象インスタンスの基本情報 ページにあるシャードリスト セクションで、シャードコンポーネントの ID を見つけます。
-
<collection_name>:コレクション名。説明show tablesコマンドを実行して、既存のコレクションをクエリできます。
例:
db.runCommand({runCommandOnShard:"shard01","command":{compact:"sharded_collection"},$queryOptions: {$readPreference: {mode: 'secondary'}}})Mongosh 1.x
構文:
db.getMongo().setReadPref('secondary') db.runCommand({runCommandOnShard:"<Shard ID>","command":{compact:"<collection_name>"}})パラメータ:
-
<シャード ID>: シャードコンポーネントの ID です。説明MongoDB コンソールにログインします。 対象のインスタンスの基本情報 ページのシャードリスト セクションで、シャードコンポーネントの ID を探します。
-
<collection_name>:コレクションの名前。説明show tablesコマンドを実行して、既存のコレクションをクエリできます。
例:
db.getMongo().setReadPref('secondary') db.runCommand({runCommandOnShard:"d-2ze91ae9d55d6604","command":{compact:"test"}})Mongosh 2.x
構文:
db.runCommand({runCommandOnShard:"<Shard ID>","command":{compact:"<collection_name>"}},{readPreference: "secondary"})パラメータ:
-
<シャード ID>: シャードコンポーネントの ID です。説明MongoDB コンソールにログインします。対象インスタンスの 基本情報 ページで、シャードリスト セクションにあるシャードコンポーネントの ID を見つけます。
-
<collection_name>: コレクションの名前。説明show tablesコマンドを実行して、既存のコレクションをクエリできます。
例:
db.runCommand({runCommandOnShard:"d-2ze657bce53fb6d4","command":{compact:"test_collection"}}, { readPreference: "secondary" }) -
-
シャードコンポーネント内のプライマリノードからディスクフラグメントを回収します。
構文:
db.runCommand({runCommandOnShard:"<Shard ID>","command":{compact:"<collection_name>",force:true}})パラメータ:
-
<Shard ID>:シャードコンポーネントの ID です。説明MongoDB コンソールにログインします。 ターゲットインスタンスの基本情報 ページのシャードリスト セクションで、シャードコンポーネントの ID を確認します。
-
<collection_name>:コレクションの名前です。説明show tablesコマンドを実行して、既存のコレクションを照会できます。 -
force: 任意。値はtrueにする必要があります。このパラメータは、シャードクラスターインスタンスがバージョン 4.2 以前を実行している場合に必要です。
例:
db.runCommand({runCommandOnShard:"shard01","command":{compact:"sharded_collection",force:true}}) -
-
-
ディスクフラグメントを回収した後、データベースが占有しているディスク領域を確認します。
db.stats()説明このコマンドは、変更せずにコピーして実行できます。
よくある質問
Q:「Compaction interrupted on table:xxx due to cache eviction pressure' on server xxx.」というエラーでコマンドが失敗します。
A: 古い低スペックのインスタンスはキャッシュプレッシャーにより compact 処理中に早期終了する可能性があります。この操作はオフピーク時間帯に実行してください。