7

我刚开始使用 mongo db 并尝试做一些简单的事情。我用包含“item”属性的数据集合填充了我的数据库。我想尝试计算每个项目在集合中的时间

文档示例:

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

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

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 吹嘘速度,我想我一定是做错了什么

Stack Overflow 上的一个问题让我查看了 mongodb 的聚合功能。所以我尝试使用 group + sum + sort thingies。想出了这个:

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

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

4

1 回答 1

9

我将给出一个基本上总结我的评论的答案。我不能代表 Hadoop 等其他技术,因为我还没有找到时间使用它们的乐趣,但我可以代表 MongoDB。

不幸的是,您对任何数据库都使用了两个最差的运算符:计算字段和全表扫描上的分组(或不同)。在这种情况下,聚合框架必须计算字段、组,然后在内存中 ( http://docs.mongodb.org/manual/reference/aggregation/#_S_sort ) 对计算字段进行排序。对于 MongoDB 来说,这是一项效率极低的任务,实际上很可能是任何数据库。

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

You can do this by pre-aggregation. So you can create another collection of grouped_wikipedia and in your application you manage this using an upsert() with atomic operators like $set and $inc (to count the occurrences) to make sure you only get one row per item. This is probably the most sane method of solving this problem.

This does however raise another problem of having to manage this extra collection alongside the detail collection wikipedia but I believe this to be a unavoidable side effect of getting the right performance here. The benefits will be greater than the loss of having to manage the extra collection.

于 2012-12-27T21:06:17.777 回答