2012-12-19 66 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; 
}