2010-12-29 8 views
39

のMongoDBドキュメントはmongodbの削除されたスペースを自動コンパクト化しますか?

(この操作はブロックして遅います注意してください)、このスペースを圧縮のmongoシェルからdb.repairDatabase()を実行することを言います。 http://www.mongodb.org/display/DOCS/Excessive+Disk+Space

私はMongoDBの無料の削除ディスクスペースを自動的を作る方法だろうか?

P.S.私たちはmongodbに最大20GBのダウンロードタスクを保存し、30分でこれを終了しました。

答えて

65

通常、データファイルを縮小する必要がない場合は、データファイルをまったく縮小しないでください。これは、ディスク上のデータファイルを「増やす」ことはかなりコストがかかる操作であり、MongoDBがデータファイルに割り当てるスペースが少なくなるため、断片化が少なくなります。

したがって、できるだけ多くのディスクスペースをデータベースに提供してください。

データベースを縮小する必要がある場合は、2つのことを念頭に置いてください。

  1. MongoDBのは、それがそうデータファイルは、その後 64メガバイト、128メガバイトなど、最大2ギガバイトのかもしれ倍増 してデータファイルだ成長(それが2GBまでのファイルを保つ に倍増停止したポイント で。)

  2. ほとんどのデータベースと同様に... に操作を行うと、 は別のジョブを に別にスケジュールする必要があります。 MongoDBには「自動縮小」がありません。実際には主要なnoSQLデータベースの (その名前を嫌う)だけRiak は、自動縮小されます。だから、 OSの スケジューラを使用して縮小を実行するジョブを作成する必要があります。あなたはbashスクリプトを使用するか、または仕事を持ってPHPスクリプトを実行する、など

サーバーサイドのJavascript

をあなたはシュリンクを行うには、サーバー側のJavaScriptを使用することができますし、それはモンゴのシェル経由JS実行することができますFOOと呼ばれるコレクションを想定すると(のcronまたはWindowsスケジューリングサービスのような)仕事を経由して定期的な拠点...

にあなたはbar.jsと実行というファイルに以下のjavascriptを救います...

$ mongo foo bar.js 

ジャバスクリプトファイルは次のようになります...

// Get a the current collection size. 
var storage = db.foo.storageSize(); 
var total = db.foo.totalSize(); 

print('Storage Size: ' + tojson(storage)); 

print('TotalSize: ' + tojson(total)); 

print('-----------------------'); 
print('Running db.repairDatabase()'); 
print('-----------------------'); 

// Run repair 
db.repairDatabase() 

// Get new collection sizes. 
var storage_a = db.foo.storageSize(); 
var total_a = db.foo.totalSize(); 

print('Storage Size: ' + tojson(storage_a)); 
print('TotalSize: ' + tojson(total_a)); 

これは何かなどを実行し、返されます...

MongoDB shell version: 1.6.4 
connecting to: foo 
Storage Size: 51351 
TotalSize: 79152 
----------------------- 
Running db.repairDatabase() 
----------------------- 
Storage Size: 40960 
TotalSize: 65153 

はどれもピーク時に(スケジュール上でこれを実行します時間)あなたは行くのが良いです。キャップされたコレクション

はしかし、capped collections一つの他のオプションがあります。

キャップされたコレクションは、非常に高いパフォーマンス 自動FIFO時代アウト機能 を(年齢アウトは、挿入順序に基づいている)持っているサイズの コレクションを固定されています。 「RRD」のコンセプトに似ていますが、それはよく知っていれば です。また

、高性能の自動キャップされコレクション 、 コレクション内のオブジェクトの挿入順序を維持します。これは特定の使用例のために非常に強力な です。ログなどの です。

基本的には、コレクションのサイズを20GBに制限し、その制限値に達するとMongoDBは最も古いレコードを破棄し、新しいレコードで置き換えます入ってくる。

これは、大量のデータを保存し、古いデータを破棄し、同じ量のディスクスペースを使用するのに最適です。

+0

感謝を素晴らしい投稿です。私がデータファイルを縮小しないと、mongodは常に多くのメモリを必要とします。どのように解決できますか? –

+0

@Zealot ...メモリ使用に関する私の答えを参照してください、それは役に立つかもしれません。 http://stackoverflow.com/questions/4468873/how-to-release-the-caching-which-is-used-by-mongodb/4482465#4482465 –

+0

私はそれを持っています、私たちは16GBのメモリを持っていて、mongodbは4GBのコストです。だから私はそれを気にしないかもしれない。これらのお返事ありがとうございます。 –

24

システムがロックされていないか、ストレージが2倍にならない場合は、db.repairDatabase()を実行するよりもうまくいく可能性のある別の解決方法があります。

レプリカセットを使用している必要があります。

私はあなたのディスクを壊す余分なデータを一旦削除したら、セカンダリレプリカを停止し、データディレクトリを消去して起動し、マスターと再同期させることを考えました。

このプロセスは時間がかかりますが、rs.stepDown()を実行すると数秒のダウンタイムが発生します。

また、これは自動化できません。まあそれはできますが、私は試してみたいとは思いません。

+0

ありがとうございます。これはレプリカセットには最適です。スペースを使い果たしたレプリカセットに必要なものでした。 – tcbcw

+2

これがトップの回答になるはずです。シンプルであり、実際の展開で機能します。 – Keeth

+0

oplogのサイズが小さすぎる(または大量のデータがある)場合、ゼロからの複製は機能しません。その後、oplogの時間間隔と複製が間にどこかで停止すると、最初の同期に時間がかかります。 – scho

8

db.repairDatabase()を実行するには、ファイルシステムで使用可能なデータベースの現在のサイズと等しいスペースが必要です。これは、コレクションが残っているか、データベースに保持する必要があるデータが現在割り当てられている容量よりもはるかに少ない領域を使用しており、修復するための十分な領域がないことを知っていると、気になることがあります。

代わりに、実際にデータの一部を保持する必要があるコレクションがほとんどない場合は、保持する必要のあるデータを新しいデータベースに移動して古いデータを削除することができます。同じデータベース名が必要な場合は、同じ名前で新しいデータベースに戻すことができます。インデックスを再作成してください。

多くのコレクションを持つデータベースのエクスポート/ドロップ/インポート操作では、同じ結果が得られる可能性がありますが、テストはしていません。

また、ポリシーとして一時的なコレクションを一時的/処理中のデータとは別のデータベースに保存し、ジョブが完了したら処理データベースを削除することもできます。MongoDBはスキーマレスなので、インデックス以外のものは失われず、プロセスの挿入が次に実行されるときにdbとコレクションが再作成されます。あなたの仕事に、適切な時に任意のネッセインデックスを作成することが含まれていることを確認してください。

4

replica setsを使用していて、この質問が当初作成されたときには利用できなかった場合は、重大な中断やパフォーマンスの問題を起こさずに自動的に領域を再利用するプロセスを設定できます。

これを行うには、レプリカセットのセカンダリの自動初期同期機能を利用します。説明するには、セカンダリをシャットダウンしてデータファイルを消去して再起動すると、セカンダリはセット内の他のノードの1つから再同期します(デフォルトでは、ping応答を見て最も近いノードを選択します回)。この再同期が発生すると、すべてのデータがゼロから書き直され(インデックスを含む)、効果的に修復と同じことが行われ、ディスクスペースが再利用されます。

これをセカンダリで実行した後、プライマリを停止してプロセスを繰り返すことで、混乱を最小限に抑えて効果的にディスク全体を再利用できます。セカンダリーから読んでいる場合は注意が必要です。セカンダリーは、潜在的に長い時間、回転から二次的に外れてしまうためです。また、あなたのoplogウィンドウが再同期を成功させるのに十分であることを確認したいのですが、これは一般に、これを行うかどうかを確認したいということです。

このプロセスを自動化するには、スクリプトを実行して、セットのメンバーごとに、好ましくは静かな時間またはメンテナンス期間中に、別の日(またはそれに類する)でこのアクションを実行するだけです。このスクリプトの非常に単純なバージョンがbashで次のようになります。

注:これは、基本的には擬似コードIS - 例示の目的のためにのみ - のための重要な変更を加えることなく、本番システムには使用しないで

#!/bin/bash 

# First arg is host MongoDB is running on, second arg is the MongoDB port 

MONGO=/path/to/mongo 
MONGOHOST=$1 
MONGOPORT=$2 
DBPATH = /path/to/dbpath 

# make sure the node we are connecting to is not the primary 
while (`$MONGO --quiet --host $MONGOHOST --port $MONGOPORT --eval 'db.isMaster().ismaster'`) 
do 
    `$MONGO --quiet --host $MONGOHOST --port $MONGOPORT --eval 'rs.stepDown()'` 
    sleep 2 
done  
echo "Node is no longer primary!\n" 

# Now shut down that server 
# something like (assuming user is set up for key based auth and has password-less sudo access a la ec2-user in EC2) 
ssh -t [email protected]$MONGOHOST sudo service mongodb stop 

# Wipe the data files for that server 

ssh -t [email protected]$MONGOHOST sudo rm -rf $DBPATH 
ssh -t [email protected]$MONGOHOST sudo mkdir $DBPATH 
ssh -t [email protected]$MONGOHOST sudo chown mongodb:mongodb $DBPATH 

# Start up server again 
# similar to shutdown something like 
ssh -t [email protected]$MONGOHOST sudo service mongodb start 
関連する問題