[英]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發生了一些事情。 幾千條記錄后,速度顯着下降。
有誰知道如何獲得有效的交錯?
您正在碰到節點異步性的奇跡。 它會將upsert請求發送到以太坊,然后繼續等待下一條記錄,而無需等待響應。 這有關系嗎,因為它只是一條信息性消息,與upsert不同步。 如果需要確保按順序完成操作,則可能需要使用異步庫來遍歷數組。
而不是預期的交錯
那只是同步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'
現在,代碼將啟動大量這些功能,這些功能又將請求發送到數據庫。 所有這些都將在第一個請求到達數據庫之前很久發生。 操作系統很可能甚至都不會打擾在您到達之前實際發送第一個TCP數據包,例如票證5或10。
要從您的評論中回答問題:不,請求將在相對較快的時間內發送出去(這取決於操作系統),但是在循環尚未完成排隊之前, 結果將不會到達您的單線程javascript代碼。 50k條目。 這是因為forEach
是您當前正在運行的代碼,並且在運行時進入的所有事件僅在完成后才進行處理-如果使用setTimeout(function() { console.log("inserted... not") }, 0)
而不是實際的數據庫調用,因為setTimeout
也是一個異步事件。
為了使代碼完全異步,您的數據源應該是提供數據的某種(異步)迭代器,而不是大量的項目。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.