增加mongodb聚合作业的内存限制

时间:2014-03-29 01:53:53

标签: mongodb memory aggregation-framework

基于聚合管道文档, “任何单个聚合操作都占用系统RAM的10%以上,操作会产生错误。” - http://docs.mongodb.org/manual/core/aggregation-pipeline-limits/

有没有办法增加这个限制?我还设置了allowDiskUse:true(因此错误不再是问题),但是想使用更多的RAM来提高性能。

背景: 我在mongodb上运行了大约1亿个条目的大型聚合作业。这基本上是对$ group的大量调用,以根据密钥合并条目。

我正在使用mongo v 2.6.0-rc2(2014年3月21日)的开发版

2 个答案:

答案 0 :(得分:5)

嗯,没有没有设置,如果你真的想到它,这是有充分理由的。因此,如果您首先考虑聚合正在做什么以及MongoDB一般做什么,那么它应该变得清晰。

"应该" 位于" head"任何合理的汇总管道:

db.collection.aggregate([
    { "$match:{ /* Something here */ } },

这些是原因:

  1. 尝试 有道理以减少您在任何操作中操作的工作集。

  2. 这也是唯一时间,您有机会使用索引来帮助搜索选择。 始终比集合扫描更好。

  3. 即使有一个内置的"优化器" ,它也可以查找"投影"限制"选择"字段,工作集大小的最佳监督是处理有效记录。后期比赛不是以这种方式"优化" 。(参见 1

  4. 接下来要考虑的是MongoDB的一般行为。因此服务器进程想要做,"消耗" 作为可用机器内存的多少,因为它可以为了保持"工作集"数据(集合和/或索引),以"工作" 最有效的方式对该数据进行操作。

    所以 确实 &#34;数据库引擎的最佳兴趣和#34; <#34;花费&#34;以这种方式大多数的内存分配。这样,您的&#34;聚合&#34; 作业和所有其他并发进程都可以访问&#34;工作数据&#34;在记忆空间。

    因此,对于MongoDB而言&#34; &#34; &#34; &#34; &#34; &#34; 只是为您正在运行的聚合操作提供服务。

    &#34;编程到硬件要求&#34; 条款中,您知道未来版本允许聚合管道实现&#34;磁盘使用&#34;为了允许更大的处理。您始终可以实施SSD或其他快速存储技术。当然,&#34; 10%&#34; 的RAM对于系统中安装的RAM量是主观的。所以你总是增加那个。

    总结一下,MongoDB有一个&#34;并发数据存储&#34; 的实际工作并且做得很好。 的是特定&#34;聚合职业选手&#34;不应该这样对待。

    因此&#34;分解&#34; 您的工作负载,或增加您的硬件规格,或者只是切换运行的大型&#34;任务&# 34;活动确实专注于正在运行的作业,例如 Hadoop风格&#34; mapReduce&#34;,并将MongoDB留给它工作提供数据。

    或者当然,将您的设计更改为&#34;预先汇总&#34; 所需的数据&#34;写入&#34;

    俗话说,&#34;马匹用于课程&#34; 使用您的工具来设计

答案 1 :(得分:1)

我能想到的解决方案有 3 种:

方案一(Mongodb): $sort 按 ID。仅使用 $group 来计算每个唯一 ID 的文档数量。然后使用 $facet$limit$skip 拆分操作。我还没有这样做,但我正准备尝试,因为我遇到了和你一样的问题。

方案一(Mongodb): 根据您的用例的查询和不同 id 的数量,您可以为每个 id 创建一个集合。这很丑陋,但如果每个请求都只针对特定的 id,那可能是有道理的。 特别是在 id 数量较少的情况下,可能没有其他解决方法,因为文档大小也有硬限制(我认为是 16MB)。嵌套在文档中的足够大的文档数组不是我认为的选项。

解决方案 3: 该解决方案将编写您自己的高度定制的数据库解决方案。分配内存,最好是一个大的顺序块。将它可以携带的所有数据放在该缓冲区中的结构数组中,该缓冲区可以始终保留在内存中或写回快速磁盘。

以毫秒为单位对内存执行大部分操作。

如果数据太大而无法在整个操作中将其保存在内存中,您可以将文件映射到内存并使用这些映射文件的视图。我在另一个项目中使用了 2 个小型 NVME,每个花费了我 40 欧元。它们一起可以在不到 3 秒的时间内将 15GB 写入磁盘,这是整个数据集所需的缓冲区大小。

我被一个朋友说服尝试使用 mongodb 来抓取变化很大的数据,目前我正在处理一个 200MB 的集合,最终会增长到这个大小的 100 倍。我正在执行的操作只是按 id 将文档分组并将根推送到数组中。 Allowdiskuse 设置为 true,但除了错误消息的措辞之外,这似乎没有任何区别。

我真的没有看到让用户根据需要调整内存限制的问题。即使人们会说使用 16GB 内存是一个坏主意,但在很多情况下绝对不是。 作为成年人,我们都应该被允许犯自己的错误。对 200MB 数据库的任何操作都不应该成为问题,尤其是像我正在执行的那样简单或无法执行的操作。