Javascript MongoDB-更新集合中所有记录的最快方法是什么?
我收集了900万张唱片。我当前正在使用以下脚本更新整个集合: simple_update.js 这将从命令行运行,如下所示:Javascript MongoDB-更新集合中所有记录的最快方法是什么?,javascript,performance,mongodb,Javascript,Performance,Mongodb,我收集了900万张唱片。我当前正在使用以下脚本更新整个集合: simple_update.js 这将从命令行运行,如下所示: mongo my_test simple_update.js 所以我所做的就是在一个简单的计算基础上添加一个新的字段pid 有没有更快的办法?这需要大量的时间。不确定是否会更快,但您可以进行多次更新。只需说updatewhere _id>0(对于每个对象都是如此),然后将“multi”标志设置为true,它应该执行相同的操作,而不必遍历整个集合 看看这个: 你可以做两件
mongo my_test simple_update.js
所以我所做的就是在一个简单的计算基础上添加一个新的字段pid
有没有更快的办法?这需要大量的时间。不确定是否会更快,但您可以进行多次更新。只需说
updatewhere _id>0
(对于每个对象都是如此),然后将“multi”标志设置为true,它应该执行相同的操作,而不必遍历整个集合
看看这个:
你可以做两件事
我不建议对较大的数据集使用{multi:true},因为它的可配置性较差 使用批量插入的更好方法 批量操作对于调度程序任务非常有用。假设您必须每天删除6个月以前的数据。使用批量操作。它的速度很快,不会降低服务器的速度。当您插入、删除或更新超过10亿个文档时,CPU、内存的使用情况并不明显。我发现{multi:true}在处理超过一百万个文档时会减慢服务器的速度(需要对此进行更多研究) 见下面的示例。这是一个js外壳脚本,也可以在服务器上作为节点程序运行。(使用npm模块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文件中,并作为mongoshell脚本执行
如果有人找到更好的方法,请更新。让我们以更快的方式使用mongo。启动
mongo 4.2
,可以接受聚合管道,最终允许基于另一个字段更新/创建字段;从而使我们能够在服务器端完全应用这种查询:
// { Y: 456, X: 3 }
// { Y: 3452, X: 2 }
db.collection.update(
{},
[{ $set: { pid: {
$sum: [ 2571, { $multiply: [ -1, "$Y" ] }, { $multiply: [ 2572, "$X" ] } ]
}}}],
{ multi: true }
)
// { Y: 456, X: 3, pid: 9831 }
// { Y: 3452, X: 2, pid: 4263 }
- 第一部分是匹配查询,过滤要更新的文档(本例中的所有文档)
- 第二部分是更新聚合管道(注意方括号表示使用聚合管道)。是一个新的聚合运算符,别名为
。请注意,如何根据同一文档中的$addFields
(X
)和$X
(Y
)的值直接创建$Y
)pid
- 不要忘记
,否则只会更新第一个匹配的文档{multi:true}
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;
}
});
// { Y: 456, X: 3 }
// { Y: 3452, X: 2 }
db.collection.update(
{},
[{ $set: { pid: {
$sum: [ 2571, { $multiply: [ -1, "$Y" ] }, { $multiply: [ 2572, "$X" ] } ]
}}}],
{ multi: true }
)
// { Y: 456, X: 3, pid: 9831 }
// { Y: 3452, X: 2, pid: 4263 }