MongoDBデータベースに、かなり前にMongoid::Versioningが有効になっているコレクションがあります。残念ながら、一部のドキュメントのサイズが非常に大きくなりました。711Kを超えるものがいくつかあります。これにより、ディスクのI/Oと読み取り/書き込みにかかる時間が高くなります。このコレクション(約200万のドキュメントがあります)を調べて、可能であれば安全にすべてのモンゴイドバージョンを削除するためのソリューションを探しています。私の知る限り、Mongoidはバージョンをその名前の配列属性に格納するだけですversions
。データベースを完全に使用できなくするような方法ですべてのドキュメントからそれを削除する方法がある場合(ディスク全体のスキャン+書き込み/更新を実行している間のパフォーマンスの観点から)、それは素晴らしいことです。
1 に答える
1
この状況に対処する方法はたくさんあります。私はこれをいくつかの異なる方法で試しましたが、1万レコードの試行では、処理時間は同じです。私は別のものを試しましたが、それははるかに悪いことがわかりました。役立つ場合に備えて、ここに添付します。
ここでは、プロセスをバッチ処理することでデータベースへの影響を軽減できるという仮説に取り組んでいます。
最初の方法は、バッチの処理に制限を設けて、コレクションで検索を実行することです。
var batchsize = 50
var c = db.collection.count()
for(x=0;x<Math.floor(c/batchsize);x++){
db.collection.find({versions: {$exists:true}}).limit(batchsize).forEach(function(cur){
db.collection.update({_id:cur._id},{$unset:{versions:""}})
})
}
ここでの問題は、すべての新しいバッチで必要となるコレクションスキャンです。制限は影響を与えるのに役立ちますが、それでもコレクションにコストがかかります。
_id
2番目の方法は、配列を持つすべてのドキュメントのsで配列を埋めてversions
から、配列を反復処理して更新することです。
var arr = db.collection.find({versions:{$exists:true}},{_id:1}).toArray()
while(arr.length>0){
for(x=0;x<batchsize;x++){
var curId = arr.pop();
db.collection.update(curId,{$unset:{versions:""}})
}
}
これは、最初の完全なコレクションスキャンを意味しますが、この時点以降は、すべてアレイを反復処理し、バッチで更新します。
3番目の方法を試しました。コレクションを調べて_id
、前の方法よりも大きいものを見つけて更新しましたが、これははるかにコストがかかることがわかりました(でインデックスを使用できたとしても_id
)。役に立つ場合に備えて、ここに追加します。
var curid = db.collection.find({_id:{$gt:MinKey}},{_id:1}).sort({_id:1}).limit(1).next()._id;
while(curid < MaxKey){
db.collection.update({_id:curid},{$unset:{versions:""}});
curid = db.collection.find({_id:{$gt:curid}},{_id:1}).sort({_id:1}).limit(1).next()._id;
}
于 2012-12-19T08:50:38.897 に答える