听了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.
谢谢.
我们的想法是,通过在分布在多台计算机上的分片数据库上使用MapReduce来提高聚合查询的性能.
我在同一台机器上用Oracle中的group-by-select语句对Mongo的Mapreduce的性能进行了一些比较.我确实发现Mongo慢了大约25倍.这意味着我必须在至少25台机器上对数据进行分片,以获得与Oracle在单台机器上提供的相同的性能.我使用了一个大约1400万个文档/行的集合/表.
通过mongoexport.exe从mongo导出数据,并将导出的数据用作Oracle中的外部表,并在Oracle中执行group-by比使用Mongo自己的MapReduce快得多.
几件事.
1)您的组查询正在处理大量数据.虽然结果集很小,但看起来它正在对集合中的所有数据进行表格缩放,以便生成那么小的结果.这可能是缓慢的根本原因.为了加快速度,您可能希望在查询运行时通过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作业,将新数据重新减少到现有集合中.然后,您可以从应用程序中查询第二个集合,而不是每次都运行组命令.
mongo中的聚合(map reduce或其他)非常慢,因为它是由javascript VM而不是数据库引擎完成的.对于时间序列数据,这仍然是这个(非常好的,imo)数据库的限制.