2012-12-19 69 views
1

我的MongoDB數據庫中有一個集合,它在一段時間之前爲它啓用了Mongoid :: Versioning。不幸的是,它使我的一些文件的大小非常大。我看到有些超過711K。這會導致昂貴的磁盤I/O和昂貴的讀取/寫入時間。我正在尋找解決方案來通過這個集合(其中有近200萬個文檔),如果可能的話,安全地刪除所有的mongoid版本。據我所知,Mongoid只是將版本存儲在一個名爲versions的數組屬性中。如果有GANK它從我的所有文件的方式,不會完全使數據庫不可用(在性能方面,而我要做整個磁盤掃描+寫入/更新)的方式,那將是巨大的。MongoDB/Mongoid,刪除文檔版本

回答

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一切都具有一個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:""}}) 
    } 
} 

這將意味着一個初始完整集合掃描,但在此之後,它將全部遍歷數組並進行批量更新。

我試過了第三種方法,在那裏我通過集合找到比前一個更大的_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; 
}