簡體   English   中英

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發生了一些事情。 幾千條記錄后,速度顯着下降。

有誰知道如何獲得有效的交錯?

您正在碰到節點異步性的奇跡。 它會將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM