簡體   English   中英

將 100 萬個對象發布到 Mongo DB 而不會耗盡內存

[英]Post 1 million object to Mongo DB without running out of memory

為了簡單起見,我在這里使用了一個 for 循環來創建一個包含 100 萬個對象的數組。

我想將數組中的每個對象發布到 mongo db。

我總是內存不足。

我知道我可以增加內存分配,但這不是我想要的解決方案。 由於超出本示例范圍的原因,我也不想使用 mongo 的批量方法。

我知道必須有一些發布這些對象的方法,這意味着每次迭代都會釋放內存(垃圾收集?) - 誰能告訴我它是什么?

謝謝!

當前代碼在這里供參考(導致分配錯誤):

var results = [];

for(var i = 1; i < 1000001; i++){

  results.push({"num":i});

}

async = require("async");
var mongodb = require('mongodb');

var MongoClient = mongodb.MongoClient;
var mongoUrl = 'mongodb://root@localhost:27017/results';

MongoClient.connect(mongoUrl, function (err, db) {

  var collection = db.collection('results');

  // 1st para in async.each() is the array of items
  async.each(results,
    // 2nd param is the function that each item is passed to
    function(item, callback){
      // Call an asynchronous function, often a save() to DB
      collection.insert(item, function (err, result) {
        if(err) console.log(err);
        console.log(item);
        callback();
      });
    },
    // 3rd param is the function to call when everything's done
    function(err){
      // All tasks are done now
      db.close();
    }
  );
});

async.each()並行運行插入,因此它基本上啟動了 1000000 個並發插入操作。

您可能希望通過使用async.eachLimit()將其限制為 100

如果要優化插入,請考慮使用批量操作,因為它還可以減少來回的網絡使用。 還存儲巨大的數組,特別是如果它們只是被計算的話,會消耗太多的內存。

var bulk = collection.initializeUnorderedBulkOp();
var count = 1, i = 0;
var bulkSize = 1000;

var generator = function (mx) {
    if(i < mx){
        return {num: i++}
    }
    return null;
}

var run = function () {
    doc = generator();
    if(doc) {
        bulk.insert(doc)
    }
    if(doc == null || count % bulkSize == 0) {
        bulk.execute(function (err, res) {
            if(err) {} // do something
            if(doc == null) {
                db.close
            }
            run();
        })
    }  
}
run()

在這里,程序的任何步驟都沒有存儲大數組。 只有在創建大容量數組時,您才會存儲它。 一旦達到bulkSize ,它也會被刷新到MongoDB

使用 setImmediate 防止內存不足錯誤

var results = [];

for(var i = 1; i < 1000001; i++){
  results.push({"num":i});
}



run(0, results.length, results, function(err){
    // do stg
});

function run(done, todo, results, callback)
{
    if(++done >= todo)
    {
        // return callback if all done
        return callback(null);
   }
    else
    {
        // save one using index
        //collection.insert(results[done], function(err, res){

       // OR save one and remove it from results
       collection.insert(results.splice(0,1),
            if(err)
                return callback(err);
            else
            {
                // use setImmediate to recall run while releasing stack
                return setImmediate(run, ++done, todo, results, callback);
            }
        });
    }
}

老問題,但我在嘗試做類似的事情時遇到了這個問題。 在嘗試插入大約 400 萬份文檔時,我的內存一直在用完。 我的解決方案是將所有數據轉儲到 JSON 文件中,例如:

用戶.json

{ "name", "John", "city": "San Francisco" }
{ "name", "Jane", "city": "New York" }

然后我使用mongoimport將文件導入 mongo:

mongoimport -u root --authenticationDatabase admin --host="localhost:27017" --db="my_db" --collection="Users" --numInsertionWorkers 4 --file="users.json"

mongoimport管理內存並有一個很好的輸出顯示(見下文)。 對於 400 萬份文檔,只用了不到 2 分鍾的時間,並且只使用了 900 MB 的 RAM。

2022-06-21T17:46:46.711+0000    [........................] my_db.Users  30.9MB/903MB (3.4%)
2022-06-21T17:46:49.714+0000    [#.......................] my_db.Users  62.2MB/903MB (6.9%)
2022-06-21T17:46:52.711+0000    [##......................] my_db.Users  93.3MB/903MB (10.3%)
2022-06-21T17:46:55.711+0000    [###.....................] my_db.Users  124MB/903MB (13.7%)
2022-06-21T17:46:58.718+0000    [####....................] my_db.Users  155MB/903MB (17.2%)
2022-06-21T17:47:01.711+0000    [####....................] my_db.Users  186MB/903MB (20.6%)
2022-06-21T17:47:04.712+0000    [#####...................] my_db.Users  217MB/903MB (24.0%)
2022-06-21T17:47:07.716+0000    [######..................] my_db.Users  248MB/903MB (27.5%)
2022-06-21T17:47:10.711+0000    [#######.................] my_db.Users  279MB/903MB (30.8%)
2022-06-21T17:47:13.712+0000    [########................] my_db.Users  310MB/903MB (34.3%)
2022-06-21T17:47:16.712+0000    [#########...............] my_db.Users  341MB/903MB (37.7%)
2022-06-21T17:47:19.713+0000    [#########...............] my_db.Users  371MB/903MB (41.0%)
2022-06-21T17:47:22.717+0000    [##########..............] my_db.Users  401MB/903MB (44.4%)
2022-06-21T17:47:25.712+0000    [###########.............] my_db.Users  432MB/903MB (47.9%)
2022-06-21T17:47:28.711+0000    [############............] my_db.Users  464MB/903MB (51.4%)
2022-06-21T17:47:31.712+0000    [#############...........] my_db.Users  495MB/903MB (54.8%)
2022-06-21T17:47:34.713+0000    [#############...........] my_db.Users  526MB/903MB (58.3%)
2022-06-21T17:47:37.711+0000    [##############..........] my_db.Users  557MB/903MB (61.7%)
2022-06-21T17:47:40.713+0000    [###############.........] my_db.Users  588MB/903MB (65.1%)
2022-06-21T17:47:43.712+0000    [################........] my_db.Users  619MB/903MB (68.6%)
2022-06-21T17:47:46.711+0000    [#################.......] my_db.Users  650MB/903MB (71.9%)
2022-06-21T17:47:49.713+0000    [##################......] my_db.Users  680MB/903MB (75.3%)
2022-06-21T17:47:52.711+0000    [##################......] my_db.Users  712MB/903MB (78.8%)
2022-06-21T17:47:55.711+0000    [###################.....] my_db.Users  742MB/903MB (82.2%)
2022-06-21T17:47:58.717+0000    [####################....] my_db.Users  766MB/903MB (84.8%)
2022-06-21T17:48:01.715+0000    [####################....] my_db.Users  783MB/903MB (86.7%)
2022-06-21T17:48:04.712+0000    [#####################...] my_db.Users  810MB/903MB (89.7%)
2022-06-21T17:48:07.720+0000    [######################..] my_db.Users  840MB/903MB (93.0%)
2022-06-21T17:48:10.711+0000    [#######################.] my_db.Users  870MB/903MB (96.3%)
2022-06-21T17:48:13.712+0000    [#######################.] my_db.Users  899MB/903MB (99.6%)
2022-06-21T17:48:14.124+0000    [########################] my_db.Users  903MB/903MB (100.0%)
2022-06-21T17:48:14.124+0000    imported 4027382 documents

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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