3

我使用以下代码循环插入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);
    }
});
4

2 回答 2

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);
    });
});
于 2012-09-07T08:11:39.330 回答
3

mongodb 就像任何其他数据库一样,需要一些时间来处理请求。您正在向它抛出一百万个请求,并且由于您的代码块中没有任何内容,这意味着在任何时候它们中的一大堆都会在某个地方排队(很可能在多个地方,其中一些在驱动程序中)代码,其他在节点的事件循环中)。这需要更多的内存。

如果没有发生排队,您将阻止或丢弃一些请求。没有免费的午餐。

于 2012-09-07T08:03:12.140 回答