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

Posted

技术标签:

【中文标题】node.js 中 MongoDB cursor.toArray() 的替代方案【英文标题】:Alternatives to MongoDB cursor.toArray() in node.js 【发布时间】:2015-06-22 21:08:31 【问题描述】:

我目前正在使用 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.15 毫秒。当然这不起作用,因为我需要转发数据,但我想知道这个函数在做什么,因为它需要这么长时间?数据库中的每个文档仅由 4 个数字组成。

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

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

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

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

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

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

【问题讨论】:

【参考方案1】:

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

一旦您开始读取游标(使用.toArray() 或使用.each().next() 遍历它),实际文档就会从数据库传输到您的客户端。该操作占用了大部分时间。

我怀疑使用.each()/.next()(而不是.toArray(),在后台使用这两者之一)会大大提高性能,但你总是可以尝试(谁知道)。由于.toArray() 将读取内存中的所有内容,因此这可能是值得的,尽管听起来您的数据集没有那么大。

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

【讨论】:

感谢您的快速回答。它让我明白了很多事情。我尝试使用 .each() 但它实际上有点慢。从数据库传输数据时,Node 应用程序是否会变慢? @KMK 对于小型文档,即使是大型数据集也不应该显着减慢您的应用程序。以我的经验,大部分减速将发生在 BSON 解析(这是一个同步操作)中。如果平台动力不足,它可能会成为瓶颈。

以上是关于node.js 中 MongoDB cursor.toArray() 的替代方案的主要内容,如果未能解决你的问题,请参考以下文章

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

如何在 node.js 中重用 mongodb 连接

如何在 MongoDB 中按日期对集合进行排序?

Node.js中使用MongoDB

node.js 中使用 Mongodb

数据未从 node.js 保存在 MongoDB 中