mongoDB 插入和 process.nextTick

mongoDB insert and process.nextTick

我有一个 50k 条目的列表,我正在输入我的数据库。

var tickets = [new Ticket(), new Ticket(), ...]; // 50k of them
tickets.forEach(function (t, ind){
    console.log(ind+1 + '/' + tickets.length);
    Ticket.findOneAndUpdate({id: t.id}, t, {upsert: true}, function (err, doc){
        if (err){
            console.log(err);
        } else {
            console.log('inserted');
        }
    });
});

而不是预期的

交错
1 / 50000
           inserted
2 / 50000
           inserted

我正在获取所有索引以及所有插入的确认信息

1 / 50000
2 / 50000
...
50000 / 50000
inserted
inserted
...
inserted

我认为 process.nextTick 有问题。几千条记录后速度明显下降。

有谁知道如何获得高效的交织?

您正在 运行 探索节点的异步性。它将更新插入请求发送到以太网中,然后继续处理下一条记录而不等待响应。这有关系吗,因为它只是一条与更新插入不同步的信息性消息。如果您需要确保它们按顺序完成,您可能想使用 Async 库来翻转数组。

Instead of the expected interleaving

这只是同步 I/O 的预期行为。

记住这些操作都是异步的,这是node.js的一个关键思想。代码的作用是这样的:

for each item in the list, 
  'start a function' // <-- this will immediately look at the next item
    output a number (happens immediately)
      do some long-running operation over the network with connection pooling 
      and batching. When done, 
         call a callback that says 'inserted'

现在,代码将启动大量函数,这些函数又会向数据库发送请求。所有这一切都将在第一个请求 到达 数据库之前很久就发生。很可能 OS 甚至懒得在你到达之前实际发送第一个 TCP 数据包,比如票 5 或 10 左右。

回答您评论中的问题:不,请求将很快发送出去(即 OS),但 结果 获胜在您的循环尚未完成对 50k 条目的排队之前,不会到达您的单线程 javascript 代码。这是因为 forEach 是您当前的 运行 代码段,所有在 运行 期间进入的事件只会在它完成后处理 - 如果您使用 setTimeout(function() { console.log("inserted... not") }, 0) 而不是实际的数据库调用,因为 setTimeout 也是一个异步事件。

要使您的代码完全异步,您的数据源应该是某种提供数据的(异步)迭代器,而不是大量的项目。