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 は、他のデータベースと同様に、リクエストの処理に時間がかかります。100 万のリクエストを投げていますが、コード ブロックには何もないため、いつでも大量のリクエストがどこかでキューに入れられます (複数の場所にある可能性が高く、そのうちのいくつかはドライバーの内部にあります)。コード、ノードのイベント ループ内のその他)。それは少し以上のメモリを必要とします。

キューイングが行われなかった場合は、一部のリクエストをブロックまたはドロップします。無料のランチなどありません。

于 2012-09-07T08:03:12.140 に答える