在进行查询时通过mongoose降低内存使用量的方法

时间:2015-07-22 23:32:42

标签: node.js mongodb memory mongoose

我正在研究节点后端尝试通过mongoose优化对mongodb的非常繁重的查询。预期的返回大小是相当大的,但由于某些原因,当我发出请求时,节点开始消耗大量内存,例如200mb +用于单个大请求。

考虑到大多数情况下回报的大小小于10mb,这似乎并不合适。它完成后也拒绝放弃内存,我知道这可能只是V8 GC执行其默认行为,但我担心的是单个find()请求消耗的大量内存。

我通过测试find()调用将其隔离。完成调用后,它会执行一些后处理,然后将数据发送到回调,所有这些都在匿名函数中。我尝试使用querystream而不是model.find(),但它没有显示真正的改进。

环顾四周没有得到任何回复,所以我会问,有没有一种已知的方法来减少,控制或优化mongoose的内存使用量?有谁知道为什么这么多的内存被用于一次通话?

修改

根据Johnny和Blakes的建议,使用精简()和流媒体的混合,并使用暂停和恢复,极大地改善了运行时和内存使用。谢谢!

2 个答案:

答案 0 :(得分:7)

只要您只需要纯JavaScript文档而不是完整的Mongoose doc实例,就可以使用lean选项进行Mongoose查询。这样可以提高性能并减少内存使用量。

model.find().lean().exec(function(err, docs) {...});

您还可以将lean()与流式处理相结合,这样可以进一步减少内存使用量。

var stream = model.find().lean().stream();

答案 1 :(得分:6)

默认的mongoose .find()当然会将所有结果作为“数组”返回,因此总是会使用大量结果的内存,因此这会留下“流”接口。

这里的基本问题是你正在使用stream接口(因为它继承自基本节点流),每个数据事件“触发”并且相关的事件处理程序被连续执行。

这意味着即使使用“流”,您在事件处理程序中的后续操作也会“堆叠”起来,至少消耗大量内存并且如果在那里发生了进一步的异步进程,可能会占用调用堆栈

因此,您可以做的最好的事情是开始“限制”流处理中的操作。这就像调用.pause()方法一样简单:

var stream = model.find().stream();   // however you call

stream.on("data",function() {
    // call pause on entry
    stream.pause();

    // do processing
    stream.resume();            // then resume when done
});

因此.pause()会停止正在发出的流中的事件,这样就可以在继续之前完成事件处理程序中的操作,这样它们就不会立即出现。

当您的处理代码完成后,您可以直接在块中调用.resume(),如此处所示,在块内执行的任何异步操作的回调块内。请注意,相同的规则适用于异步操作,并且“all”必须在您应该调用resume之前发出完成信号。

还可以应用其他优化,您可以查看“队列处理”或“异步流控制”可用模块以帮助您通过某些并行执行来获得更高的性能。

但基本上认为.pause()然后处理并.resume()继续避免在处理过程中占用大量内存。

此外,请注意您的“输出”,并且如果为响应构建某些内容,请尝试再次使用“流”。如果你正在做的工作只是在内存中构建另一个变量,所有这一切都将是徒劳的,所以有助于意识到这一点。