我目前正在使用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的新手。
答案 0 :(得分:7)
db.collection.find()
返回一个光标,而不是结果,打开一个光标非常快。
开始阅读光标(使用.toArray()
或使用.each()
或.next()
遍历),实际文档正在从数据库传输给你的客户。该操作大部分时间都在占用。
我怀疑使用.each()/.next()
(代替.toArray()
,而不是.toArray()
,其中使用了其中之一)将大大提高性能,但您可以随时尝试(谁知道)。由于{{1}}将读取内存中的所有内容,因此它可能是值得的,尽管听起来不像您的数据集那么大。
我真的认为Raspberry Pi上的MongoDB(特别是Model 1)不能很好地运行。如果您不太依赖MongoDB查询功能,则应考虑使用备用数据存储。甚至可能是内存存储(500个文档乘以4个数字听起来不像需要大量的RAM)。