2012-12-27 68 views
7

我刚刚开始与mongo db并试图做一些简单的事情。我用包含“item”属性的数据集合填充了我的数据库。我想尝试计数每个项目多少时间是集合中的文档的像MapReduce一样慢的MongoDB聚合?

例如:

{ "_id" : ObjectId("50dadc38bbd7591082d920f0"), "item" : "Pons", "lines" : 37 } 

所以我设计了这两个函数做的MapReduce(用Python编写的使用pymongo)

all_map = Code("function() {" 
      " emit(this.item, 1);" 
      "}") 

all_reduce = Code("function (key, values) {" 
        " var sum = 0;" 
        " values.forEach(function(value){" 
        "  sum += value;" 
        " });" 
        " return sum;" 
        "}") 

这就像一个魅力,所以我开始填充集合。在大约30,000个文档中,mapreduce已经持续了一秒多的时间...因为NoSQL对速度吹牛我以为我一定在做东西错了!

堆栈溢出问题在这里让我看看mongodb的聚集功能。所以我尝试使用group + sum + sort thingies。想到这个:

db.wikipedia.aggregate(
{ $group: { _id: "$item", count: { $sum: 1 } } }, 
{ $sort: {count: 1} } 
) 

这段代码工作得很好,给了我mapreduce设置相同的结果,但它也一样慢。难道我做错了什么?我真的需要使用其他工具,如hadoop以获得更好的性能

+1

$ group不能使用索引,然后你正在进行全表扫描和排序计算字段,再次不能使用索引...嗯,是的,我认为这可能很容易如慢,先生,看看$ sort的注意事项:http://docs.mongodb.org/manual/reference/aggregation/#_S_sort。如果我是诚实的,我不认为这是工具的错误,但更多的模式设计,如果你需要做这样的实时查询 - 这需要时间 – Sammaye

+0

阅读这个澄清:http:// stackoverflow.com/questions/12015064/mongodb-mapreduce-and-sorting –

+0

@Sammaye当你读完我的结尾句子时,你会注意到我并没有对这些工具大发雷霆。我还没有使用NoSQL和MongoDB的经验。我只是问什么是错的。我怎样才能改进我的设计,让这件事情以正确的方式运行。 – Arninja

回答

9

我会基本总结我的意见。我不能说像Hadoop这样的其他技术人员,因为我还没有找到时间使用它们的乐趣,但我可以为MongoDB发言。

不幸的是,你正在使用两个最差的运营商的任何数据库:计算字段和分组(或独特)的全表扫描。在这种情况下,聚合框架必须计算字段,组和内存(http://docs.mongodb.org/manual/reference/aggregation/#_S_sort)对计算字段进行排序。对于MongoDB来说,这是一个非常低效的任务,实际上很可能是任何数据库。

没有简单的方法可以根据自己的应用程序实时执行此操作。如果您不需要立即返回结果,Map Reduce可能是一条出路,但由于我猜测您并不是真的想等待这种类型的东西,所以默认方法就是完全根除组。

您可以通过预先聚合来完成此操作。因此,您可以创建另一个grouped_wikipedia集合,并在您的应用程序中使用upsert()$set$inc(以计算出现次数)等原子运算符来管理此操作,以确保每个item只获得一行。这可能是解决这个问题最理智的方法。

然而,这却产生了另一个问题,就是不得不管理这个额外的集合,并与详细集合wikipedia并存,但我相信这是在这里获得正确性能的不可避免的副作用。好处将大于不必管理额外收集的损失。

+0

但是,如果你有一个拥有8百万条目的集合,并且你正在不断地运行映射和减少以保持你的“缓存”是最新的,那么这是否会减慢你的分贝? –

+0

@RobertReiz它可能会影响到很多因素。我的意思是你确实拥有一个JS引擎的权重,但JS enigne不再是单线程的,它可以在处理数据库时释放对数据库的锁定,所以问题在于一旦MR但是,如果你运行一个只读出的MR,每5分钟就有10,000行,你会发现MongoDB可以非常满意地处理这个问题 – Sammaye

+0

我不太关心客户端,而是mongodb进程。假设我有8百万条记录,并且对于每个条目,MongoDB MR需要5分钟,那么我需要27天来计算我的所有缓存。这远离实时:-) –