MongoDB-更新集合中所有记录的最快方法是什么?

问题描述 投票:38回答:5

我有一个收藏有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

有更快的方法吗?这需要大量时间。

javascript performance mongodb
5个回答
28
投票
您可以做两件事。

    将'multi'标志设置为true发送更新。
  1. 在服务器端存储功能并尝试使用server-side code execution
  • 该链接还包含以下建议:

    这是执行批量管理工作的好技术。通过本地主机接口在服务器上运行mongo。这样,连接速度非常快,延迟很短。这比db.eval()更友好,因为db.eval()阻止了其他操作。

    这可能是最快的。您必须意识到,在单个服务器上发布9M更新将是一项繁重的工作。假设您每秒可以获得3k的更新,但您仍在谈论要运行近一个小时。

    这并不是真正的“ mongo问题”,那将是硬件限制。


  • 18
    投票
    我正在使用:db.collection.update method

    // db.collection.update( criteria, objNew, upsert, multi ) // --> for reference db.collection.update( { "_id" : { $exists : true } }, objNew, upsert, true);


    3
    投票
    我不建议将{multi: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。


    0
    投票
    不确定是否会更快,但是您可以进行多次更新。只需说update where _id > 0(对每个对象都是如此),然后将“ multi”标志设置为true,它就应该执行相同的操作,而不必遍历整个集合。

    检查此:MongoDB - Server Side Code Execution


    0
    投票
    [开始Mongo 4.2db.collection.update()可以接受聚合管道,最终允许基于另一个字段更新/创建一个字段;从而使我们能够完全应用这种查询服务器端:
    © www.soinside.com 2019 - 2024. All rights reserved.