在听了很多有关MongoDB性能的好消息后,我们决定让Mongodb尝试解决我们遇到的问题。我开始将我们在几个mysql数据库中的所有记录移动到mongodb中的单个集合。这导致了一个 2900万个文档的集合(每个文档至少有20个字段),在HD中占用大约100 GB的空间。我们决定将它们全部放在一个集合中,因为所有文档都具有相同的结构,我们想要查询并汇总所有这些文档的结果。
我创建了一些索引以匹配我的查询,否则即使简单的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。
谢谢。
答案 0 :(得分:22)
我们的想法是,通过在分布在多台计算机上的分片数据库上使用MapReduce来提高聚合查询的性能。
我在同一台机器上用Oracle中的group-by-select语句对Mongo的Mapreduce的性能进行了一些比较。我确实发现Mongo慢了大约25倍。这意味着我必须在至少25台机器上对数据进行分片,以获得与Oracle在单台机器上提供的相同的性能。我使用了一个大约1400万个文档/行的集合/表。
通过mongoexport.exe从mongo导出数据,并将导出的数据用作Oracle中的外部表,并在Oracle中执行group-by比使用Mongo自己的MapReduce快得多。
答案 1 :(得分:8)
夫妻俩。
1)您的群组查询正在处理 lot 数据。虽然结果集很小,但看起来它正在对集合中的所有数据进行表格缩放,以便生成那么小的结果。这可能是缓慢的根本原因。为了加快速度,您可能希望在查询运行时通过iostat查看服务器的磁盘性能,因为这可能是瓶颈。
2)正如其他答案中所指出的,group命令使用javascript解释器,这将限制性能。您可以尝试使用在2.1中作为beta发布的新聚合框架(注意:这是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作业,将新数据重新减少到现有集合中。然后,您可以从应用程序中查询第二个集合,而不是每次都运行组命令。
答案 2 :(得分:6)
mongo中的聚合(map reduce或其他)非常慢,因为它是由javascript VM而不是数据库引擎完成的。对于时间序列数据,这仍然是这个(非常好的,imo)数据库的限制。