[Node.js]循环通过本机驱动程序将1000000个文件插入mongodb,为什么节点会占用大量内存?

时间:2012-09-07 07:48:02

标签: node.js node-mongodb-native

我使用以下代码循环插入1000000文档到mongodb,但我发现节点进程占用了大量内存,我的客户端已经死了。

db.collection("batch_insert", function (err, collection) {
    if (!err) {
        var count = 0;
        for (var i = 0; i < 1000000; i++) {
            collection.insert({hello:'world', ok:'OKOKOK'}, {safe:true, serializeFunctions:false}, function (err, result) {
                count++;
                if (1000000 == count) {
                    db.close();
                }
            });
        }
    } else {
        console.log(err);
    }
});

2 个答案:

答案 0 :(得分:8)

您的for周期阻止事件循环。并且在将所有查询发送到nextTick之前,它无法转到mongodb并处理查询结果。您需要使用异步方式批量插入数据。 像这样:

var mongo = require('mongodb');

var Inserter = function (collection) {
    this.collection = collection;
    this.data = [];
    this.maxThreads = 6;
    this.currentThreads = 0;
    this.batchSize = 5000;
    this.queue = 0;
    this.inserted = 0;
    this.startTime = Date.now();
};

Inserter.prototype.add = function(data) {
    this.data.push(data);
};

// Use force=true for last insert
Inserter.prototype.insert = function(force) {
    var that = this;
    if (this.data.length >= this.batchSize || force) {
        if (this.currentThreads >= this.maxThreads) {
            this.queue++;
            return;
        }
        this.currentThreads++;
        console.log('Threads: ' + this.currentThreads);
        this.collection.insert(this.data.splice(0, this.batchSize), {safe:true}, function() {
            that.inserted += that.batchSize;
            var currentTime = Date.now();
            var workTime = Math.round((currentTime - that.startTime) / 1000)
            console.log('Speed: ' + that.inserted / workTime + ' per sec');
            that.currentThreads--;
            if (that.queue > 0) {
                that.queue--;
                that.insert();
            }
        });
    }
};

var db = new mongo.Db('test', new mongo.Server('localhost', 27017, {}), {native_parser:false});
db.open(function(err, db) {
    db.collection('test', function(err, collection) {
        var inserter = new Inserter(collection);
        setInterval(function() {
            for (var i = 0; i < 5000; i++) {
                inserter.add({test:'test'});
            }
            inserter.insert();
        }, 0);
    });
});

答案 1 :(得分:3)

mongodb,就像任何其他数据库一样,需要一些时间来处理请求。你在它上面扔了一百万个请求,因为你的代码块没有任何内容,这意味着它们在任何时候都会在某个地方排队(很可能是在多个地方,其中一些在驱动程序内部)代码,节点的事件循环中的其他代码)。这需要一点点记忆。

如果排队没有发生,你可以阻止或删除一些请求。没有免费午餐这样的事情。