【问题标题】:Quickly add identical metadata when inserting thousands of records in MongoDB?在 MongoDB 中插入数千条记录时快速添加相同的元数据?
【发布时间】:2015-11-05 12:24:35
【问题描述】:

我想insert an array 将数千个对象放入一个 MongoDB 集合中。

db.col.insert(
   [
     { },
     { },
     { } // A couple of 1000s more
   ],
   {
       ordered : false,
       writeConcern : 0
   }
);

但是,我还想使用元数据来识别这些组。数组中的每条记录都需要分配一些数据,并且该数据对于数组中的所有记录都是相同的。

有没有一种方法可以插入所有文档,并为所有文档设置例如:

{
    dateTime : '111111111',
    groupId  : 'some hash',
    batchId  : 'other hash'
}

没有手动将其手动添加到数组中的数千条记录中?那将是一个很大的性能下降(而且很丑)。

我曾经将这些记录与元数据一起添加为一个数组:

{
    dateTime : '111111111',
    groupId  : 'some hash',
    batchId  : 'other hash',
    batchArr : [ array with thousands of records]
}

并在上面使用$unwind。但是,这不再可能,因为记录数开始超过 MongoDB 的16 MB BSON size limit

【问题讨论】:

    标签: arrays performance mongodb


    【解决方案1】:

    这将是 Bulk API 操作的一个很好的候选者。有两种类型的批量操作:

    • 有序批量操作。这些操作按顺序执行所有操作,并在第一次写入错误时出错。
    • 无序批量操作。这些操作并行执行所有操作并聚合所有错误。无序批量操作不保证执行顺序。

    考虑初始化一个 Bulk() 操作构建器并添加一系列插入操作以批量添加多个文档,从而简化您的性能:

    var bulk = db.col.initializeOrderedBulkOp(),
        objectList = [{}, {}, ..., {}], // array with thousands of records 
        counter = 0,
        metadata = {
            dateTime : '111111111',
            groupId  : 'some hash',
            batchId  : 'other hash'
        };      
    
    objectList.forEach(function(obj) {
        obj["dateTime"] = metadata.dateTime;
        obj["groupId"] = metadata.groupId;
        obj["batchId"] = metadata.batchId;
    
        bulk.insert(obj);
        counter++;
    
        if (counter % 500 == 0) {
            bulk.execute();             
            bulk = db.col.initializeOrderedBulkOp();            
        }
    });
    
    // Catch any under or over the 500's
    if (counter % 500 != 0) {
        bulk.execute();
    }
    

    【讨论】:

    • 使用Bulk API的额外积分。赞成。但是,这仍然会在大型阵列上执行forEach(),这会导致开销。我正在删除尽可能多的forEach()es 以减少执行时间,我特别想知道是否有办法在不添加更多forEach() 的情况下执行此查询。
    • forEach() 方法仅仅代表了一个循环,它为批量执行添加对象,只要你坚持添加大批量的同一类操作,在这种情况下批量插入,你可以确定将您的代码与底层写入协议相匹配。尝试设置一个合成微基准,在其中插入 1000 条不使用批量 API 的记录和使用批量 API 的记录,您将看到巨大的性能提升。因此,请意识到forEach() 充当循环来准备批量操作批次。
    • 我没看到。要么我的微基准测试错误,要么col.insertMany(array)bulk 一样优化。我不确定。
    • 顺便问一下,您使用的是哪个版本的 MongoDB,因为 Bulk API 仅适用于 2.6 及更高版本?
    • 使用2.6.11作为最低版本。
    猜你喜欢
    • 1970-01-01
    • 2016-05-23
    • 2014-05-25
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 2013-01-15
    • 2012-10-19
    • 1970-01-01
    相关资源
    最近更新 更多