delete コマンドまたは TTL インデックスを使用してデータが削除された後、物理ディスク領域は自動的に解放されません。 未使用の空き領域はディスクフラグメントになります。 本トピックでは、自動再利用プラン、コンソールからの手動再利用、および compact コマンドという 3 つの再利用方法について説明します。
再利用方法の選択
ApsaraDB for MongoDB では、delete コマンドまたは TTL インデックスを使用してデータが削除された後、物理ディスク領域は自動的に解放されません。 削除されたデータが占有していた領域は空き領域としてマークされ、将来の書き込みのために予約されます。 再利用されずに残った部分がディスクフラグメントになります。 フラグメントの蓄積によってディスク使用率が高くなった場合は、フラグメントを再利用して物理領域を解放する必要があります。
3 つの再利用方法を以下に比較します。
|
比較項目 |
方法 1:自動再利用プラン |
方法 2:コンソールからの手動再利用 |
方法 3:コマンドラインによる compact |
|
対象ノード |
Hidden ノードのみ |
Hidden ノードのみ |
プライマリノードまたは セカンダリノード |
|
カーネルバージョンの要件 |
|
|
なし |
|
1回あたりの再利用可能な領域の上限 |
100 GB |
なし |
なし |
|
サービスへの影響 |
なし (メンテナンスウィンドウ中に実行) |
なし (Hidden ノードを対象) |
あり。 詳細については、「compact のワークロードへの影響」をご参照ください。 |
|
ユースケース |
再利用可能な領域が少ないコレクションが多数ある場合に適しています。 |
再利用可能な領域が多いコレクションに適しています。 |
大容量、精密な制御、またはコンソールでの再利用が不十分な場合 |
コレクションまたはデータベース全体で drop を実行すると、その物理領域は即座に解放されます。 しかし、これはデータ削除操作であり、ディスク領域が逼迫している場合やインスタンスがロックされている場合の緊急措置としてのみ使用すべきです。 日常的なフラグメント再利用方法ではありません。
方法 1:自動再利用プランの設定
ApsaraDB for MongoDB は、Database Autonomy Service (DAS) を利用したフラグメント再利用プランを提供します。 DAS は、インスタンスのメンテナンスウィンドウ中に Hidden ノードを自動的に検出し、compact を実行します。 手動での介入は不要で、プロセスがワークロードに影響を与えることはありません。
トリガー条件とルール
システムは、以下の条件を同時に満たすコレクションからのみ、フラグメントを自動的に再利用します。
-
インデックス領域とデータ領域の合計サイズが 1 GB を超えている。
-
断片化率が 20% を超えている。
追加ルール:
-
1 回の再利用の上限は 100 GB です。 超過分は次回以降に再利用されます。
-
上記のしきい値はシステムに組み込まれており、カスタマイズすることはできません。
設定のエントリポイント
-
MongoDB コンソールにログインし、対象のインスタンスに移動します。
-
ナビゲーションペインで、[CloudDBA] > ストレージ分析 を選択します。
-
データスペース リストで、断片化率 列を見つけ、リサイクル リンクをクリックします。
-
表示される 断片の再利用計画 ダイアログボックスで、計画の追加 をクリックして確定します。
方法 2:コンソールからの手動再利用
この方法は、コレクションの再利用可能な領域が 100 GB を超える場合に使用します。
コレクションの再利用可能な領域が 100 GB を超える場合、再利用には 1 時間以上かかることがあります。 それに応じて再利用時間を計画してください。
操作手順
-
対象のインスタンスに移動します。 ナビゲーションペインで、[CloudDBA] > ストレージ分析 を選択します。
-
データスペース リストで、各コレクションの断片化率と再利用可能な領域を表示します。
-
断片化率が高く再利用したいコレクションについて、対応する リサイクル ボタンをクリックします。
再利用結果の確認
再利用が完了したら、再度ストレージ分析を実行し、対象コレクションの断片化率が減少したかどうかを確認します。 再利用が実行されたのと同じノードを表示していることを確認してください (「よくある質問とトラブルシューティング」をご参照ください)。
コマンドライン経由でプライマリノードまたはセカンダリノードで compact を実行した場合、コンソールのストレージ分析の断片化率は変化しません。 これは再利用が失敗したことを意味するものではありません。 Monitoring Information ページに移動し、実際に操作を実行したノードに切り替えて結果を確認してください。
方法 3:コマンドラインによる compact
この方法は、単一のコレクションが 100 GB を超える場合、コンソールでの再利用が不十分な場合、または精密な制御が必要な場合に使用します。
権限要件
compact を実行するには、アカウントに dbAdmin または hostManager (バージョン > 8.0) 権限が必要です。 そうでない場合、権限エラーが報告されます。
not authorized on <database> to execute command { compact: ... }
compact のワークロードへの影響
-
読み取り/書き込みのブロッキングとパフォーマンスへの影響
-
MongoDB 4.4 より前:
compactコマンドはコレクションを含むデータベースをロックし、そのデータベースに対するすべての読み取りおよび書き込み操作をブロックします。 断片化が深刻な場合、compactの完了に時間がかかり、Hidden ノードでレプリケーションラグが発生する可能性があります。 オフピーク時間に実行するか、書き込みワークロードに基づいて oplog サイズを増やすか、フラグメントを再利用する前に「データベースのメジャーバージョンのアップグレード」を参照して MongoDB 4.4 以降にアップグレードすることを推奨します。 -
MongoDB 4.4 以降:
compactコマンドは読み取りおよび書き込み操作をブロックしなくなりましたが、実行中にパフォーマンスに影響を与える可能性があります。 オフピーク時間に実行することを推奨します。
-
-
ノードの再構築
-
MongoDB 3.4 (すべてのバージョン)、MongoDB 4.0 (すべてのバージョン)、MongoDB 4.2 の初期マイナーバージョン (4.0.22 以前)、および MongoDB 4.4 の初期マイナーバージョン (5.0.6 以前):
compactを実行しているノードは RECOVERING 状態になります。 この状態が長すぎると、ヘルスチェックコンポーネントがノードを異常と判断し、自動再構築をトリガーする可能性があります。 MongoDB のバージョン情報については、「MongoDB のマイナーバージョン」をご参照ください。 -
新しいバージョンを実行しているインスタンスの場合:
compactを実行しているノードは SECONDARY 状態のままで、再構築をトリガーしません。
-
-
バージョンに関係なく、プライマリノードへの影響を避けるため、常に Hidden ノードまたはセカンダリノードからのフラグメントの再利用を優先してください。 ディスクフラグメントを再利用する前に、「データベースのバックアップ」を推奨します。
compact の実行時間
実行時間はデータ量、システム負荷、その他の要因に依存し、正確に見積もることはできません。 断片化が多い大規模なコレクションほど時間がかかります。 非常に大きなコレクション (数百 GB) は、大幅に時間がかかる場合があります。 dryRun: true を使用してまず再利用可能な領域を見積もり、オフピーク時間に操作を実行することを推奨します。
以下のデータは参考としてのみ提供されています。
実環境テスト (MongoDB 4.4):断片化率が 50% の約 2.5 GB のコレクションで compact を実行したところ、約 5 秒かかり、約 1.9 GB の領域が解放されました。
compact が効果的でないシナリオ
以下のシナリオでは、compact コマンドが効果を発揮しない可能性があります。
-
物理的なコレクションサイズが 1 MB 未満である。
-
断片化率が 20% 未満である。
-
ファイルの最初の 80% に 20% 未満の空き領域しか存在しない、またはファイルの最初の 90% に 10% 未満の空き領域しか存在しない。
詳細については、「block_compact」をご参照ください。
レプリカセットインスタンス
プライマリノードで compact を直接実行することは推奨されません。 compact は大量の I/O および CPU リソースを消費し、プライマリノードで実行するとオンラインのワークロードに影響を与える可能性があります。 セカンダリノードで実行し、その後フェイルオーバーでノードをローテーションして各ノードを順番に再利用することを推奨します。
スタンドアロン (StandAlone) インスタンスにはノードが 1 つしかありません。 それに接続して compact を直接実行します。
セカンダリノードに接続し、以下のコマンドを実行します。
use <database>
// 再利用前:比較のためにデータベース領域の使用状況を確認します
db.stats()
// ドライラン:実際に再利用せずに、再利用可能な領域を見積もります
db.runCommand({ compact: "<collection>", dryRun: true })
// 実際の再利用
db.runCommand({ compact: "<collection>" })
// 再利用後:再度確認して領域を比較します
db.stats()
dryRun: true パラメーターはドライランモードを有効にし、ファイルを変更せずに estimatedBytesFreed (解放可能なバイト数の見積もり) のみを返します。 ドライランの結果を確認した後、このパラメーターを削除して実際の再利用を実行します。 再利用の前後に db.stats() を実行してデータベース領域の使用状況を比較し、結果を確認します。
同じコレクションで新しい compact 操作を開始する前に、前の compact 操作が完了していることを確認してください。
シャードクラスターインスタンス
シャードクラスターの場合、Shard コンポーネント内の対応するノードからのみフラグメントを再利用する必要があります。 Mongos および ConfigServer コンポーネントはユーザーデータを保存しないため、再利用は不要です。
シャードクラスターの読み取り専用ノードは compact コマンドをサポートしていないため、読み取り専用 (ReadOnly) ノードからフラグメントを再利用することはできません。
セカンダリノードのフラグメントの再利用:runCommandOnShard を実行する場合、読み取り設定を Secondary に設定する必要があります。 構文はクライアントによって異なります。 お使いのクライアントに適した方法を選択してください。
mongosh 2.x
mongosh 2.x は、runCommand の 2 番目のパラメーターで読み取り設定を直接指定することをサポートしています。
db.runCommand({runCommandOnShard:"<Shard ID>","command":{compact:"<collection_name>"}},{readPreference: "secondary"})
mongosh 1.x
mongosh 1.x では、コマンドを実行する前に setReadPref を介して読み取り設定を行う必要があります。
db.getMongo().setReadPref('secondary')
db.runCommand({runCommandOnShard:"<Shard ID>","command":{compact:"<collection_name>"}})
mongo shell (レガシー)
mongo shell (レガシー) では、$queryOptions を追加して読み取り設定を指定する必要があります。
db.runCommand({runCommandOnShard:"<Shard ID>","command":{compact:"<collection_name>"},$queryOptions: {$readPreference: {mode: 'secondary'}}})
プライマリノードのフラグメントの再利用 (推奨されません):
サービスへの影響を最小限に抑えるため、プライマリ/セカンダリのフェイルオーバーを実行してプライマリノードをセカンダリノードに切り替え、その後新しいセカンダリノードからフラグメントを再利用することを推奨します。 プライマリ/セカンダリのフェイルオーバーの手順については、「シャードクラスターインスタンスのプライマリ/セカンダリ切り替え」をご参照ください。
db.adminCommand({
runCommandOnShard: "<shardId>",
dbName: "<database>",
command: { compact: "<collection>", force: true }
})
よくある質問とトラブルシューティング
再利用を実行したが、目に見える効果がない
次の項目を順番に確認してください。
-
操作と検証の間のノードの不一致 (最も一般的な原因):コンソールのストレージ分析は Hidden ノードからフラグメントを再利用し、ページにはデフォルトで Hidden ノードの断片化率が表示されます。 コマンドラインの compact は、接続したノードに影響します。 プライマリノードまたはセカンダリノードで compact を実行したが、コンソールのストレージ分析で断片化率を確認した場合、数値は変わりません。 正しいアプローチ:Monitoring Information ページに移動し、実際に操作を実行したノードに切り替えてディスク領域の使用率を表示します。
-
内部ファイルの断片化:compact は、ファイルの末尾にある連続した空き領域のみを切り詰めることができます。 ファイル内の再利用可能な領域は再利用できません。 フラグメントがファイル内部に分散している場合、compact 後もディスク領域はほとんど変わらないことがあります。 これは WiredTiger ストレージエンジンの想定される動作であり、失敗ではありません。
db.<collection>.stats()を実行し、freeStorageSizeとstorageSizeの比率を確認して、再利用可能な領域を見積もります。 -
再利用のしきい値未満:断片化率が 20% 未満、物理的なコレクションサイズが 1 MB 未満、またはコレクションが小さい場合、絶対的な再利用可能領域は非常に小さく、再利用しても目に見える効果がない場合があります。
-
プライマリノードの保護により操作がブロックされた:
use force:true to forceが表示された場合、これは compact がプライマリノードで実行されたことを示す保護メカニズムです。 force を使用しないでください。 代わりに、Hidden ノードまたはセカンダリノードで compact を実行するか、コンソールのストレージ分析を使用して Hidden ノードを再利用してください。
断片化率が 0% にならないのはなぜですか?
これは想定される動作です。 compact はファイルの末尾にある連続した空き領域のみを再利用します。 ファイル内の再利用可能な領域は、将来の書き込みのために保持されます。 そのため、通常、断片化率が 0% になることはありません。 これは WiredTiger ストレージエンジンの設計上の仕様です。
エラー:Interrupted ... cache eviction pressure
原因:compact の実行中、WiredTiger ストレージエンジンでキャッシュエビクションのプレッシャーが発生します。 古いバージョンや小規模な仕様のインスタンスは、メモリリソースが限られています。 キャッシュプレッシャーが高くなりすぎ、エンジンが時間内にページを退避できない場合、compact は中断され、早期に終了します。
解決策:オフピーク時間中に再試行するか、プライマリ/セカンダリのフェイルオーバーをトリガーして再試行するか、再利用する前にインスタンスの仕様をアップグレードします。
ディスクフルでインスタンスがロックされているときに compact を実行できますか?
はい、可能です。 ディスクがフルになると、インスタンスはロック状態になります。 書き込み (insert) および削除 (delete) 操作は cloud instance error, disk locked... というエラーで拒否されますが、find、compact、および drop 操作は引き続き実行できます。
なぜ delete 操作も拒否されるのですか?
delete 操作自体が oplog に書き込み、依然としてディスク領域を消費するため、ロック状態では拒否されます。 しかし、drop と compact はメタデータレベルまたは領域再編成の操作であり、システムによって許可されます。 ロック状態では、compact を実行してフラグメントを再利用して領域を解放するか、drop を実行してコレクションを削除して領域を解放することができます。 どちらもスケールアップを必要としない復旧パスです。
最速の復旧判断
|
お客様の状況 |
推奨されるアクション |
復旧速度 |
コスト |
|
安全に削除できる未使用のコレクションまたはデータベースがある。 |
|
領域を解放した後、インスタンスは約 4〜5 分で自動的にロック解除されます (検出遅延があり、即時ではありません)。 |
コストはかかりませんが、データは削除されます。 データが削除可能であることを確認してください。 |
|
データは削除できないが、再利用すべき重要なフラグメントがある。 |
compact を実行します (compact はロック状態で許可されます)。 |
compact が領域を解放した後、インスタンスは約 5 分で自動的にロック解除されます (検出遅延があり、即時ではありません)。 |
|
|
削除するデータがない / データを失うことはできない。 |
ストレージ領域のスケールアップを行います。 |
スケーリング完了後にロック解除されます。 |
|
ロック解除後、ディスクが再びいっぱいになるのを防ぐために、速やかにフラグメントを再利用するか、未使用のデータをクリーンアップしてください。 「ディスク領域の枯渇によるインスタンスロックの解決」をご参照ください。
コンソールの使用率がアラートと一致しない (例:コンソールは 60% なのにアラートは 90% でトリガーされる)
これは表示ディメンションが異なるために発生するもので、データエラーではありません。
-
アラートは「単一ノードで最も高い値」でトリガーされる:レプリカセットでは、プライマリノード、セカンダリノード、および Hidden ノードのディスク使用率が異なる場合があります (セカンダリ/Hidden ノードは、oplog、再利用のタイミング、一時ファイルなどの理由でプライマリノードよりも高くなることが多い)。 いずれか 1 つのノードがしきい値を超えると、アラートがトリガーされます。
-
コンソールはデフォルトで「最も高いノード」を表示しない:インスタンスの [基本情報] ページは集計値を表示し、ストレージ分析 ページはデフォルトで Hidden ノードを表示します。 どちらもアラートをトリガーしたノードよりも低い場合があります。
各ノードの実際の使用率を確認する方法:インスタンスの Monitoring Information ページに移動し、表示モードを [サブノード独立] に切り替えると、各プライマリ/セカンダリノードのディスク領域使用率を個別に表示して、使用率が高くアラートをトリガーしたノードを見つけることができます。
プライマリノードとセカンダリノードのディスク使用率が異なる理由とその対処法についての詳細は、「ApsaraDB for MongoDB インスタンスの高いディスク領域使用率」をご参照ください。
ディスクをダウンサイジングしてコストを節約できますか?
ダウンサイジングはサポートされていません。 ApsaraDB for MongoDB は、どのバージョンでも購入したディスク領域の縮小をサポートしていません。 大量のデータをクリーンアップし、フラグメントを再利用した場合でも、ディスク仕様を維持または増加させることしかできません。 直接縮小することはできません。
より小さなディスク仕様が必要な場合、唯一の選択肢は、より小さな仕様で新しいインスタンスを作成し、DTS を使用してデータを移行し、その後元のインスタンスを解放することです。 続行する前に、移行コストとダウンタイムウィンドウを評価してください。
構成変更と仕様の制限については、「レプリカセットインスタンスの構成変更」をご参照ください。
付録
ディスクフラグメントはなぜ発生するのか?
delete コマンドまたは TTL の有効期限切れを使用してデータが削除されると、それは削除済みとしてマークされるだけです。 それが占有していた領域は、すぐにオペレーティングシステムに返されません。 代わりに、将来の書き込みのために空きブロックとして保持されます。 削除が書き込みを上回ると、これらの空きブロックは長期間未使用のままとなり、フラグメントを形成します。 これが、データ量が減少してもディスク使用率が高いままになる理由です。
ディスクフラグメントを再利用するタイミング
以下の状況でディスクフラグメントの再利用を検討してください。
-
大量のデータを削除した後:多数のドキュメントを削除すると、解放された領域はオペレーティングシステムに返されず、将来の書き込みのために予約されるため、ディスク上にかなりの断片化された領域が残ります。
重要手動削除 (
delete) および TTL の有効期限切れでは、ディスクフラグメントは自動的に再利用されません。 手動での再利用が必要です。 -
長期間の高書き込みワークロードの後:持続的な高書き込みワークロード (頻繁な挿入、更新、削除) は、ディスク上に徐々に断片化された領域を蓄積します。
-
ディスク領域が少なく、断片化が 20% を超える場合:ディスク使用率が 85%〜90% 以上に達した場合、フラグメントを再利用することで領域を解放し、ストレージの圧迫を軽減できます。
再利用可能な領域の表示と見積もり
インスタンスに接続し (レプリカセットインスタンスの場合は、サービスへの影響を最小限に抑えるためにセカンダリノードに接続します)、db.runCommand({collStats: "<collection>"}) を実行してコレクションのストレージステータスを表示します。 次のフィールドに注意してください。
-
size:コレクションの論理ストレージサイズ。 -
storageSize:コレクションの物理ストレージサイズ。 -
freeStorageSize:コレクション内の再利用可能な空き領域 (MongoDB 4.4 以降で利用可能)。
remove コマンドでドキュメントを削除した後、size は減少しますが、storageSize は変わらない場合があります。 freeStorageSize と storageSize の比率が高いほど、断片化率が高いことを示します。
次のコマンドを実行して、コレクションの再利用可能なフラグメント領域を見積もることもできます (再利用可能なバイト数を返します)。
db.<collection>.stats().wiredTiger["block-manager"]["file bytes available for reuse"]
ほぼ空のインスタンスの場合、freeStorageSize は null を返すことがあります。 この場合、wiredTiger["block-manager"]["file bytes available for reuse"] (再利用可能なバイト数) と ["file size in bytes"] (合計ファイルサイズ) を確認して、断片化率を見積もります。 フィールドの説明については、「collStats の出力」をご参照ください。