2015-02-06 137 views
24

我有一个有数百万行的mongoDB集合,我试图优化我的查询。我目前正在使用聚合框架来检索数据并按照我的意愿对它们进行分组。我典型的聚合查询是这样的:$match > $group > $ group > $project

但是,我注意到最后的部分只需要几毫秒,开始是最慢的。

我试着只用$ match过滤器执行查询,然后用collection.find执行相同的查询。聚合查询需要大约80ms,而find查询需要0或1ms。

我在几乎每个领域的索引,所以我想这不是问题。有什么想法可能会出错?或者这只是聚合框架的一个“正常”缺陷?

我可以用找到的查询,而不是聚集查询,但是我会请求后,进行大量的处理,这个过程能够尽快与$group等来这样做,我宁愿保持聚合框架。

感谢,

编辑:

这里是我的准则:

{ 
    "action" : "click", 
    "timestamp" : { 
      "$gt" : ISODate("2015-01-01T00:00:00Z"), 
      "$lt" : ISODate("2015-02-011T00:00:00Z") 
    }, 
    "itemId" : "5" 
} 
+0

你可以发布你的'$匹配'并找到?在大多数用法中,'$ match'和find应该是等价的,但我想确切地看到您正在比较哪些语句以便做出准确的答案。此外,你是否先运行聚合,然后查找?如果你反复重复两遍并比较时间,会发生什么?差异可能是将结果从磁盘移动到内存中的成本。 – wdberkeley 2015-02-06 16:07:34

+0

我在第一篇文章中添加了标准,但是即使没有时间戳标准,我也看到了很大的差距。但是现在我想知道它是否与find()返回一个游标并仅显示第一个结果有关。 – Owumaro 2015-02-06 16:13:41

+7

好吧,我有很多无用的索引,所以我清理了一切,并创建了一个复合索引(与我的$匹配过滤器的字段)。现在我有良好的表现和相同的表现,寻找和聚合$匹配:)问题解决了。 – Owumaro 2015-02-09 13:04:31

回答

14

aggregation framework的主要目的是缓解一个大数量的条目的查询并生成一个低数对你有价值的结果。如您所说,您也可以使用多个find查询,但请记住,您不能使用find查询创建新字段。另一方面,$group阶段允许您定义新的字段。

如果你想实现aggregation framework的功能,你很可能必须运行一个初始的find(或连锁几个),拉动这些信息并用编程语言进一步处理它。

aggregation pipeline似乎需要更长的时间,但至少你知道你只需要考虑到一个系统的性能 - MongoDB引擎。

鉴于,当涉及操纵从find查询返回的数据时,您很可能必须用编程语言进一步操作数据,从而增加了复杂性,具体取决于选择的编程语言的复杂性。

+9

感谢您的信息。不过,我仍然不明白为什么只有$ match过滤器的聚合查询不如使用相同过滤器的简单find查询快。 – Owumaro 2015-02-06 12:56:01

3

您是否尝试过使用explain()来查找查询?它会给你一个很好的想法,find()查询会花费多少时间。您可以使用$ explain &进行$匹配,查看索引访问&其他参数是否有任何区别。

此外,聚合框架的$ group部分不使用索引,因此它必须处理聚合框架的$ match阶段返回的所有记录。因此,为了更好地理解查询的工作情况,请参阅结果集,它返回&是否适合要由MongoDB处理的内存。