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
也是一个异步事件。
要使您的代码完全异步,您的数据源应该是某种提供数据的(异步)迭代器,而不是大量的项目。
我有一个 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
也是一个异步事件。
要使您的代码完全异步,您的数据源应该是某种提供数据的(异步)迭代器,而不是大量的项目。