我有一个收藏有900万条记录。我目前正在使用以下脚本来更新整个集合:
simple_update.js
db.mydata.find().forEach(function(data) {
db.mydata.update({_id:data._id},{$set:{pid:(2571 - data.Y + (data.X * 2572))}});
});
这是从命令行运行的,如下所示:
mongo my_test simple_update.js
所以我要做的就是根据简单的计算添加一个新字段pid。
有更快的方法吗?这需要大量时间。
这是执行批量管理工作的好技术。通过本地主机接口在服务器上运行mongo。这样,连接速度非常快,延迟很短。这比db.eval()更友好,因为db.eval()阻止了其他操作。
这可能是最快的。您必须意识到,在单个服务器上发布9M更新将是一项繁重的工作。假设您每秒可以获得3k的更新,但您仍在谈论要运行近一个小时。
这并不是真正的“ mongo问题”,那将是硬件限制。
// db.collection.update( criteria, objNew, upsert, multi ) // --> for reference
db.collection.update( { "_id" : { $exists : true } }, objNew, upsert, true);
使用批量插入的更好方法。
批量操作对于调度程序任务确实很有帮助。假设您每天必须删除早于6个月的数据。使用批量操作。它的速度很快,不会减慢服务器速度。当您插入,删除或更新十亿个文档时,CPU的内存使用情况并不明显。当您处理超过百万个文档时,我发现{multi:true}降低了服务器的速度(需要对此进行更多研究。)
请参见下面的示例。这是一个js shell脚本,也可以作为节点程序在服务器中运行。(使用npm module shelljs或类似的脚本来实现)
将mongo更新到3.2 +
更新多个唯一文档的正常方法是
let counter = 0;
db.myCol.find({}).sort({$natural:1}).limit(1000000).forEach(function(document){
counter++;
document.test_value = "just testing" + counter
db.myCol.save(document)
});
我尝试了310-315秒。更新一百万个文档需要5分钟以上的时间。我的收藏包括1亿多份文档,因此其他文档的速度可能有所不同。
使用批量插入的相同之处是
let counter = 0; // magic no.- depends on your hardware and document size. - my document size is around 1.5kb-2kb // performance reduces when this limit is not in 1500-2500 range. // try different range and find fastest bulk limit for your document size or take an average. let limitNo = 2222; let bulk = db.myCol.initializeUnorderedBulkOp(); let noOfDocsToProcess = 1000000; db.myCol.find({}).sort({$natural:1}).limit(noOfDocsToProcess).forEach(function(document){ counter++; noOfDocsToProcess --; limitNo--; bulk.find({_id:document._id}).update({$set:{test_value : "just testing .. " + counter}}); if(limitNo === 0 || noOfDocsToProcess === 0){ bulk.execute(); bulk = db.myCol.initializeUnorderedBulkOp(); limitNo = 2222; } });
最佳时间是8972毫秒。因此,平均而言,更新一百万个文档仅用10秒。比旧方法快30倍。将代码放入.js文件中,并作为mongo shell脚本执行。
[如果有人找到更好的方法,请更新。让我们以更快的方式使用mongo。
update where _id > 0
(对每个对象都是如此),然后将“ multi”标志设置为true,它就应该执行相同的操作,而不必遍历整个集合。Mongo 4.2
,db.collection.update()
可以接受聚合管道,最终允许基于另一个字段更新/创建一个字段;从而使我们能够完全应用这种查询服务器端: