草庐IT

MongoDB 聚合性能

coder 2023-05-04 原文

我们遇到了长时间运行(几分钟)聚合查询的问题。

收藏:

我们收集了 2.5 亿个文档,每个文档大约有 20 个字段, 集合的总大小为 110GB。

我们对“our_id”和 dtKey 字段有索引。

硬件:

内存:

24GB RAM(6 * 4GB DIMM 1333 Mhz)

磁盘:

Lvm 11TB 由 4 个 3TB 磁盘构建而成:

  • 最大瞬时数据传输速度为 600MB/s。

  • 7200 RPM 主轴。平均延迟 = 4.16ms

  • RAID 0

CPU:

2* E5-2420 0 @ 1.90GHz 总共 12 个内核,24 个线程。 戴尔 R420。

问题: 我们正在尝试对以下内容进行聚合查询:

db.our_collection.aggregate(
    [
        {
            "$match":
            {
                "$and":
                    [
                        {"dtKey":{"$gte":20140916}},
                        {"dtKey":{"$lt":20141217}},
                        {"our_id":"111111111"}
                    ]
            }
        },
        {
            "$project":
            {
                "field1":1,
                "date":1
            }
        },
        {
            "$group":
            {
                "_id":
                {
                    "day":{"$dayOfYear":"$date"},
                    "year":{"$year":"$date"}
                },
                "field1":{"$sum":"$field1"}
            }
        }
    ]
);

这个查询需要几分钟才能运行,当它运行时我们可以看到以下内容:

  • Mongo 当前操作产生超过 30 万次
  • 在 iostat 上,我们看到 ~100% 的磁盘利用率

这个查询完成后,它似乎在缓存中,可以在瞬间再次完成,

在为 3 – 4 个用户运行后,第一个似乎已经从缓存中换出,查询又需要很长时间。

我们测试了匹配部分的计数,发现我们有 50K 文档的用户以及 500K 文档的用户,

我们试图只得到匹配的部分:

db.pub_stats.aggregate(
    [
        {
            "$match":
            {
                "$and":
                    [
                        {"dtKey":{"$gte":20140916}},
                        {"dtKey":{"$lt":20141217}},
                        {" our_id ":"112162107"}
                    ]
            }
        }
    ]
);

而且查询似乎占用了大约 300-500M 的内存,

但运行完整查询后,似乎占用了 3.5G 内存。

问题:

  1. 为什么聚合的流水线需要这么多内存?
  2. 我们如何提高性能以使其在 HTTP 请求的合理时间内运行?

最佳答案

  1. Why the pipelining of the aggregation takes so much memory?

只需执行 $match 就不必读取实际数据,它可以在索引上完成。通过 field1 的投影访问,实际的文档必须被读取,并且它可能也会被缓存。

另外,分组 can be expensive .通常情况下,如果你的分组阶段需要超过 100M 的内存,它应该会报错 - 你使用的是什么版本?它需要在产生之前扫描整个结果集,而 MongoDB 至少必须存储组中每个元素的指针或索引。我猜内存增加的关键原因是前者。

  1. How can we increase our performance for it to run on a reasonable time for HTTP request?

您的 dtKey 似乎对时间进行了编码,并且分组也是根据时间完成的。我会尝试利用这一事实 - 例如,通过预先计算每天的聚合和 our_id 组合 - 如果没有更多标准并且数据不再发生太大变化,则很有意义。

否则,我会尝试将 {"our_id":"111111111"} 标准移动到第一个位置,因为相等性应该始终在范围查询之前。我猜聚合框架的查询优化器足够聪明,但值得一试。此外,您可能想尝试将您的两个索引变成一个复合索引 { our_id, dtkey }。现在支持索引交集,但我不确定它的效率有多高,真的。使用内置配置文件和 .explain() 分析您的查询。

最后,MongoDB 专为大量写入使用而设计,在几毫秒内从磁盘扫描数百 GB 的数据集在计算上根本不可行。如果您的数据集大于您的 RAM,您将面临数十毫秒甚至更高、数万或数十万次的大规模 IO 延迟,因为所有必需的磁盘操作。请记住,使用随机访问,您将永远无法接近理论上的顺序磁盘传输速率。如果你不能预先计算,我想你需要更多的内存。也许 SSD 会有所帮助,但这只是猜测。

关于MongoDB 聚合性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27544323/

有关MongoDB 聚合性能的更多相关文章

  1. Ruby 的数字方法性能 - 2

    我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0

  2. ruby - Ruby 性能中的计时器 - 2

    我正在寻找一个用ruby​​演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent

  3. ruby-on-rails - 如果条件与 &&,是否有任何性能提升 - 2

    如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:

  4. ruby - Rails Elasticsearch 聚合 - 2

    不知何故,我似乎无法获得包含我的聚合的响应...使用curl它按预期工作:HBZUMB01$curl-XPOST"http://localhost:9200/contents/_search"-d'{"size":0,"aggs":{"sport_count":{"value_count":{"field":"dwid"}}}}'我收到回复:{"took":4,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":90,"max_score":0.0,"hits":[]},"a

  5. ruby - 如何找到我的 Ruby 应用程序中的性能瓶颈? - 2

    我编写了一个Ruby应用程序,它可以解析来自不同格式html、xml和csv文件的源中的大量数据。我如何找出代码的哪些区域花费的时间最长?有没有关于如何提高Ruby应用程序性能的好资源?或者您是否有任何始终遵循的性能编码标准?例如,你总是用加入你的字符串吗?output=String.newoutput或者你会使用output="#{part_one}#{part_two}\n" 最佳答案 好吧,有一些众所周知的做法,例如字符串连接比“#{value}”慢得多,但是为了找出您的脚本在哪里消耗了大部分时间或比所需时间更多,您需要进行分

  6. c# - Ruby 等效于 C# Linq 聚合方法 - 2

    什么是Linq聚合方法的ruby​​等价物。它的工作原理是这样的varfactorial=new[]{1,2,3,4,5}.Aggregate((acc,i)=>acc*i);每次将数组序列中的值传递给lambda时,变量acc都会累积。 最佳答案 这在数学以及几乎所有编程语言中通常称为折叠。它是更普遍的变形概念的一个实例。Ruby从Smalltalk中继承了这个特性的名称,它被称为inject:into:(像aCollectioninject:aStartValueinto:aBlock一样使用。)所以,在Ruby中,它称为inj

  7. STM32的HAL和LL库区别和性能对比 - 2

    LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L

  8. ruby - GC.disable 的任何性能缺点? - 2

    是否存在GC.disable会降低性能的情况?只要我使用的是真正的RAM而不是交换内存,就可以这样做吗?我正在使用MRIRuby2.0,据我所知,它是64位的,并且使用的是64位的Ubuntu:ruby2.0.0p0(2013-02-24revision39474)[x86_64-linux]Linux[redacted]3.2.0-43-generic#68-UbuntuSMPWedMay1503:33:33UTC2013x86_64x86_64x86_64GNU/Linux 最佳答案 GC.disable将禁用垃圾回收。像rub

  9. ruby-on-rails - Rails with angular 与 Rails pure(查看性能) - 2

    我尝试在Internet上搜索有关使用angularJS进入RubyonRails项目与RubyonRailspure的View性能的信息。我的问题是因为2个月前我开始使用纯AngularJS,现在我需要将AngularJS集成到一个新项目中,但需要展示使用带有RubyonRails的AngularJS呈现View的性能如何,并消除对RubyonRails的负担.例如:带Rails的Angular:使用RubyonRails获取数据(从数据库或GET请求),将信息发送到file.js.erb并使用AngularJS操作数据并显示带有解析数据的View。纯粹的Rails:(自然流程)使用

  10. ruby-on-rails - 在 Rails 3 应用程序中使用 require_dependency 对性能有何影响? - 2

    我觉得我理解require和require_dependency之间的区别(来自Howarerequire,require_dependencyandconstantsreloadingrelatedinRails?)。但是,我想知道如果我使用一些不同的方法(参见http://hemju.com/2010/09/22/rails-3-quicktip-autoload-lib-directory-including-all-subdirectories/和Bestwaytoloadmodule/classfromlibfolderinRails3?)来加载所有文件会发生什么,所以我们:

随机推荐