2010-04-08 42 views
27

在听到MongoDB性能的诸多好消息之后,我们决定让Mongodb尝试解决我们遇到的问题。我开始将我们在多个mysql数据库中的所有记录移动到mongodb中的单个集合中。这导致收集了29百万个文件(其中每个文件至少有20个字段),这需要大约100 GB的空间。我们决定将它们全部放在一个集合中,因为所有文档具有相同的结构,并且我们要查询并汇总所有这些文档的结果。MongoDB在聚合查询方面的表现

我创建了一些索引来匹配我的查询,否则即使简单count()也需要很长时间。但是,诸如distinct()和group()之类的查询仍然需要很长时间。

实施例:

// creation of a compound index  
db.collection.ensureIndex({'metadata.system':1, 'metadata.company':1}) 

// query to get all the combinations companies and systems 
db.collection.group({key: { 'metadata.system':true, 'metadata.company':true }, reduce: function(obj,prev) {}, initial: {} }); 

我把一看的mongod日志和它有很多这样的线(在执行上述查询):

Thu Apr 8 14:40:05 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1048890 nreturned:417 154ms 
Thu Apr 8 14:40:08 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1050205 nreturned:414 430ms 
Thu Apr 8 14:40:18 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1049748 nreturned:201 130ms 
Thu Apr 8 14:40:27 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1051925 nreturned:221 118ms 
Thu Apr 8 14:40:30 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1053096 nreturned:250 164ms 
... 
Thu Apr 8 15:04:18 query database.$cmd ntoreturn:1 command reslen:4130 1475894ms 

此查询了1475894ms其比我想象的要长(结果列表大约有60个条目)。首先,鉴于我收藏的大量文件,这是否是预期的?一般来说聚合查询在MongoDB中会如此缓慢?关于如何改善表现的任何想法?

我正在一台双核和10GB内存的单机上运行mongod。

谢谢。

+1

那么这个问题太老了,当你搜索MongoDB聚合框架时,仍然会涉及搜索引擎。马里奥你没有提到你的MongoDB版本,因为他们在2.4中改进了很多AF,而且我在一个蹩脚的m1上做了这个。 EC2与3.7G内存在一个69米的集合,它的速度比以前更快。你有没有尝试过新版本,或者你有不同的方法?当然,AF和MapReduce有很多基准,但看看10Gen的最新版本http://blog.mongodb.org/post/62900213496/qaing-new-code-with-mms-map-reduce-vs -aggregation tnx – Maziyar 2013-11-03 02:16:08

+0

感谢您的评论。这是在2010年,我相信我们正在使用MongoDB 1.4.0之类的东西。已经有一段时间了,我相信很多事情在MongoDB中都有变化,但自那年晚些时候以来我一直没有在这个项目中工作:) – 2013-11-05 17:34:54

+0

感谢Mario的回复。我刚开始使用MongoDB(大约一年),只是想知道你的项目发生了什么。无论如何祝你好运:) – Maziyar 2013-11-06 03:19:07

回答

22

这个想法是,您可以通过在分布在多台机器上的分片数据库上使用MapReduce来提高聚合查询的性能。

我在同一台机器上对Mongo的Mapreduce与Oracle中的group-by-select语句进行了一些比较。我确实发现Mongo大约慢了25倍。这意味着我必须在至少25台机器上分割数据,才能获得与Oracle在单台机器上交付的Mongo相同的性能。我使用了大约1400万个文档/行的集合/表格。

通过mongoexport.exe导出mongo中的数据,并将导出的数据作为Oracle中的外部表使用,并且在Oracle中执行group-by比使用Mongo自己的MapReduce快得多。

+0

这将是非常有用的知道哪个版本的MongoDB。 – nilskp 2013-08-14 13:18:50

+0

我相信这是类似于1.4.0版本的东西。这是在2010年。 – 2013-11-06 17:19:34

4

聚合(map reduce或其他)在mongo中非常缓慢,因为它是由JavaScript VM而不是数据库引擎完成的。这仍然是时间序列数据的这个(非常好,imo)db的限制。

+1

从v2.2开始,聚合管道使用[本地操作](http://docs.mongodb.org/manual/core/aggregation-introduction/#aggregation-pipelines)。 – Tamlyn 2015-09-03 13:17:20

8

夫妇的事情。

1)您的小组查询正在处理批次的数据。虽然您的结果集很小,但它看起来像是在对您的集合中的所有数据进行表格比例缩放以产生小的结果。这可能是缓慢的根源。为了加快速度,您可能希望在查询运行时通过iostat查看服务器的磁盘性能,因为这可能是瓶颈。

2)正如在其他答案中已经指出的那样,group命令使用JavaScript解释器,这会限制性能。您可以尝试使用在2.1版中作为测试版发布的新聚合框架(注意:截至2012年2月24日这是一个不稳定的版本)。请参阅http://blog.mongodb.org/post/16015854270/operations-in-the-new-aggregation-framework以获得很好的介绍。这不会克服(1)中的数据量问题,但它是用C++实现的,如果JavaScript时间是瓶颈,那么它应该快得多。

3)另一种方法是使用增量式map-reduce以分组结果生成第二个集合。想法是,您将运行map-reduce作业来聚合一次结果,然后定期运行另一个map-reduce作业,将新数据重新还原到现有集合中。然后,您可以从您的应用程序查询第二个集合,而不是每次都运行组命令。