1

我的 MongoDB 数据库中有一个集合,很久以前就启用了 Mongoid::Versioning。不幸的是,它使我的一些文档变得非常大。我看到一些超过 711K。这导致昂贵的磁盘 i/o 和昂贵的读/写时间。我正在寻找一个解决方案来遍历这个集合(它有近 200 万个文档),并尽可能安全地删除所有 mongoid 版本控制。据我所知,Mongoid 只是将版本存储在一个名为 that, 的数组属性中versions。如果有一种方法可以从我的所有文档中获取它,并且不会完全使数据库无法使用(在我执行整个磁盘扫描 + 写入/更新时的性能方面),那就太好了。

4

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所有具有数组的文档的 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:""}})
    }
}

这将意味着初始的完整集合扫描,但在此之后,它会遍历数组并批量更新。

我尝试了第三种方法,在该方法中,我通过集合找到_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 回答