node.js中MongoDB cursor.toArray()的替代方法

时间:2015-04-16 12:43:20

标签: node.js performance node-mongodb-native

我目前正在使用MongoDB游标的toArray()函数将数据库结果转换为数组:

run = true;
count = 0;
var start = process.hrtime();
db.collection.find({}, {limit: 2000}).toArray(function(err, docs){
  var diff = process.hrtime(start);
  run = false;
  socket.emit('result', {
    result: docs,
    time: diff[0] * 1000 + diff[1] / 1000000,
    ticks: count
  });
  if(err) console.log(err);
});

此操作在我的计算机上大约需要7毫秒。如果我删除.toArray()函数,那么操作大约需要0.15ms。当然这不起作用,因为我需要转发数据,但是我想知道函数是做什么的,因为它花了这么长时间?数据库中的每个文档只包含4个数字。

最后,我希望在一个更小的处理器上运行它,比如Raspberry Pi,这里从数据库中获取500个文件并将其转换为数组的操作大约需要230毫秒。这对我来说似乎很重要。或者我只是期待太多?

有没有其他方法可以在不使用toArray()的情况下从数据库中获取数据?

我注意到的另一件事是整个Node应用程序在获取数据库结果时显着减慢。我创建了一个简单的间隔函数,它应该每1 ms增加一次计数值:

setInterval(function(){
  if(run) count++;
}, 1);

然后我希望计数值与时间几乎相同,但是在我的计算机上16 ms的时间内,计数值为3或4.在Raspberry Pi上,计数值从未递增。什么占用了这么多CPU?监视器告诉我,当我被要求重复运行数据库查询时,我的计算机使用了27%的CPU,Raspberry Pi使用了92%的CPU和11%的RAM。

我知道这是很多问题。任何帮助或解释都非常感谢。我还是Node和MongoDB的新手。

1 个答案:

答案 0 :(得分:7)

db.collection.find()返回一个光标,而不是结果,打开一个光标非常快。

开始阅读光标(使用.toArray()或使用.each().next()遍历),实际文档正在从数据库传输给你的客户。该操作大部分时间都在占用。

我怀疑使用.each()/.next()(代替.toArray(),而不是.toArray(),其中使用了其中之一)将大大提高性能,但您可以随时尝试(谁知道)。由于{{1}}将读取内存中的所有内容,因此它可能是值得的,尽管听起来不像您的数据集那么大。

我真的认为Raspberry Pi上的MongoDB(特别是Model 1)不能很好地运行。如果您不太依赖MongoDB查询功能,则应考虑使用备用数据存储。甚至可能是内存存储(500个文档乘以4个数字听起来不像需要大量的RAM)。