我使用以下代码循环插入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);
}
});
答案 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,就像任何其他数据库一样,需要一些时间来处理请求。你在它上面扔了一百万个请求,因为你的代码块没有任何内容,这意味着它们在任何时候都会在某个地方排队(很可能是在多个地方,其中一些在驱动程序内部)代码,节点的事件循环中的其他代码)。这需要一点点记忆。
如果排队没有发生,你可以阻止或删除一些请求。没有免费午餐这样的事情。