在查询的时候用mongoose来降低内存使用的方法
我正在研究节点后端,试图通过mongoose来优化对mongodb的非常大的查询。 预期的返回大小是相当可观的,但是由于某种原因,当我发出请求时,节点开始消耗大量的内存,例如200MB +用于一个大的请求。
考虑到大多数情况下,回报的规模小于10mb,这似乎并不正确。 在完成之后,它也拒绝释放内存,我知道这可能只是V8 GC的默认行为,但是我担心的是,单个find()请求会消耗大量的内存。
我通过testingfind()调用来隔离它。 一旦完成了调用,它将执行一些后处理,然后将数据发送到一个callback函数,全部使用匿名函数。 我曾尝试使用查询stream而不是model.find(),但它显示没有真正的改进。
环顾四周没有得到任何回应,所以我会问,有没有一种已知的方法来减less,控制或优化mongoose的内存使用? 有谁知道为什么如此多的内存被用于一个单一的电话?
编辑
根据Johnny和Blakes的build议,使用lean()和streaming的混合,并使用暂停和恢复,极大地改善了运行时和内存的使用。 谢谢!
只要您只需要普通的JavaScript文档而不需要完整的Mongoose文档实例,就可以使用精简选项来使用Mongoose查询。 这样可以提高性能并减less内存使用量。
model.find().lean().exec(function(err, docs) {...});
您还可以将lean()
与stream式传输结果相结合,从而进一步减less内存使用量。
var stream = model.find().lean().stream();
默认.find()
当然会返回所有的结果作为一个“数组”,所以总是要使用大量结果的内存,所以这留下了“stream”接口。
这里的基本问题是你正在使用一个stream接口(因为这是从基本节点streaminheritance的),每个数据事件“触发”并且相关的事件处理程序连续执行。
这意味着,即使对于“stream”,事件处理程序中的后续操作也是“堆栈”的,至less消耗大量内存,并且如果在那里进一步发生asynchronous进程,可能会吃掉调用堆栈。
所以你可以做的最好的事情就是开始“限制”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()
停止正在发送的stream中的事件,这样可以让事件处理程序中的动作在继续之前完成,以便它们不会一次全部到达。
当你的处理代码完成的时候,你可以直接在块内执行.resume()
,如图所示,在块内执行的任何asynchronous操作的callback块中。 请注意,同样的规则适用于asynchronous操作,并且在调用简历之前,“全部”必须表示完成。
还有其他的优化方法可以应用,你可能会希望看到一个“队列处理”或“asynchronousstream控制”可用的模块,以帮助你通过一些并行的执行来获得更多的性能。
但基本上可以这样认为.pause()
然后处理和.resume()
继续避免在处理中占用大量内存。
另外,要注意你的“输出”,并且同样尝试再次使用一个“stream”,如果build立一些响应。 如果你所做的工作实际上只是在内存中build立另一个variables,所有这一切都将毫无用处,所以有助于了解这一点。