我有一些元数据和一大堆项目。我以前将它存储在mongo中,并通过$unwind
数组查询它。
但是,在极端情况下,阵列变得如此之大,以至于我遇到了16MB的BSON限制。
所以我需要将数组的每个元素存储为一个单独的文档。为此,我需要将元数据添加到所有这些,所以我可以找回它们。 It is suggested that I use bulk operations为此。
然而,表现似乎真的很慢。插入一个大文档几乎是即时的,这需要十秒。
var bulk = col.initializeOrderedBulkOp();
var metaData = {
hash : hash,
date : timestamp,
name : name
};
// measure time here
for (var i = 0, l = array.length; i < l; i++) { // 6000 items
var item = array[i];
bulk.insert({ // Apparently, this 6000 times takes 2.9 seconds
data : item,
metaData : metaData
});
}
bulk.execute(bulkOpts, function(err, result) { // and this takes 6.5 seconds
// measure time here
});
批量插入6000个文档,总共38 MB的数据(在MongoDB中转换为49 MB作为BSON),性能似乎无法接受。 将元数据附加到每个文档的开销可能不是那么糟糕,对吧?更新两个索引的开销可能不好,对吗?
我错过了什么吗?是否有更好的方法来插入需要作为一组提取的文档组?
这不仅仅是我的笔记本电脑。在服务器上相同。让我觉得这不是配置错误,而是编程错误。
将MongoDB 2.6.11
与节点适配器node-mongodb-native 2.0.49
-update -
只需将元数据添加到批量帐户中的每个元素 2.9秒。需要有更好的方法来做到这一点。
答案 0 :(得分:1)
批量发送批量插入操作,因为这样可以减少到服务器的流量,从而通过不在单个语句中发送所有内容来执行高效的有线事务,而是分解为服务器承诺的可管理块。使用这种方法在回调中等待响应的时间也更少。
更好的方法是使用 async 模块,因此即使循环输入列表也是非阻塞操作。选择批量大小可能会有所不同,但是选择每1000个条目的批量插入操作可以使其保持在16MB BSON硬限制之下,因为整个“请求”等于一个BSON文档。
下面演示如何使用 async 模块迭代数组并重复调用迭代器函数,而test返回true。停止时或发生错误时调用回调。
var bulk = col.initializeOrderedBulkOp(),
counter = 0,
len = array.length,
buildModel = function(index){
return {
"data": array[index],
"metaData": {
"hash": hash,
"date": timestamp,
"name": name
}
}
};
async.whilst(
// Iterator condition
function() { return counter < len },
// Do this in the iterator
function (callback) {
counter++;
var model = buildModel(counter);
bulk.insert(model);
if (counter % 1000 == 0) {
bulk.execute(function(err, result) {
bulk = col.initializeOrderedBulkOp();
callback(err);
});
} else {
callback();
}
},
// When all is done
function(err) {
if (counter % 1000 != 0) {
bulk.execute(function(err, result) {
console.log("More inserts.");
});
}
console.log("All done now!");
}
);