MongoDB MapReduce比纯Java处理慢得多?
我想数一数我的文档(包括嵌入文档)的所有密钥。 首先,我编写了一个Java客户机来解决这个问题。显示结果不到4秒。 然后我编写了一个map/reduce函数。结果很好,但运行该功能需要30秒以上! 我认为map/reduce函数会更快,因为它是在服务器端执行的。Java客户机需要从服务器获取每个文档,但速度要快得多。 为什么会这样 //以下是我的地图功能:MongoDB MapReduce比纯Java处理慢得多?,java,performance,mongodb,mapreduce,Java,Performance,Mongodb,Mapreduce,我想数一数我的文档(包括嵌入文档)的所有密钥。 首先,我编写了一个Java客户机来解决这个问题。显示结果不到4秒。 然后我编写了一个map/reduce函数。结果很好,但运行该功能需要30秒以上! 我认为map/reduce函数会更快,因为它是在服务器端执行的。Java客户机需要从服务器获取每个文档,但速度要快得多。 为什么会这样 //以下是我的地图功能: map = function(){ for(var key in this) { emit(key, {count:1}
map = function(){
for(var key in this) {
emit(key, {count:1});
if(isNestedObject(this[key])){
m_sub(key, this[key]);
}
}
}
reduce = function (key, emits) {
total = 0;
for (var i in emits) {
total += emits[i].count;
}
return {count:total};
}
//这是我的reduce函数:
map = function(){
for(var key in this) {
emit(key, {count:1});
if(isNestedObject(this[key])){
m_sub(key, this[key]);
}
}
}
reduce = function (key, emits) {
total = 0;
for (var i in emits) {
total += emits[i].count;
}
return {count:total};
}
//以下是对mapreduce的调用:
mr = db.runCommand({"mapreduce":"keyword", "map" : map, "reduce" : reduce,
"scope":{
isNestedObject : function (v) {
return v && typeof v === "object";
},
m_sub : function(base, value) {
for(var key in value) {
emit(base + "." + key, {count:1});
if(isNestedObject(value[key])){
m_sub(base + "." + key, value[key]);
}
}
}
}
})
//以下是输出:
{
"result" : "tmp.mr.mapreduce_1292252775_8",
"timeMillis" : 39087,
"counts" : {
"input" : 20168,
"emit" : 986908,
"output" : 1934
},
"ok" : 1
}
00:03:726
duration:3726 ms
1898
//这是我的Java客户端:
public static Set<String> recursiv(DBObject o){
Set<String> keysIn = o.keySet();
Set<String> keysOut = new HashSet<String>();
for(String s : keysIn){
Set<String> keys2 = new HashSet<String>();
if(o.get(s).getClass().getSimpleName().contains("Object")){
DBObject o2 = (DBObject) o.get(s);
keys2 = recursiv(o2);
for(String s2 : keys2){
keysOut.add(s + "." + s2);
}
}else{
keysOut.add(s);
}
}
return keysOut;
}
public static void main(String[] args) throws Exception {
final Mongo mongo = new Mongo("xxx.xxx.xxx.xxx");
final DB db = mongo.getDB("keywords");
final DBCollection keywordTable = db.getCollection("keyword");
Multiset<String> count = HashMultiset.create();
long start = System.currentTimeMillis();
DBCursor curs = keywordTable.find();
while(curs.hasNext()){
DBObject o = curs.next();
Set<String> keys = recursiv(o);
for(String s : keys){
count.add(s);
}
}
long end = System.currentTimeMillis();
long duration = end - start;
System.out.println(new SimpleDateFormat("mm:ss:SS").format(Long.valueOf(duration)));
System.out.println("duration:" + duration + " ms");
//System.out.println(count);
System.out.println(count.elementSet().size());
}
不要担心结果的不同数量(1934年与1898年)。这是因为map reduce计数也是数组中java客户端未计数的键。
感谢您介绍不同的执行时间。这不是一个很好的答案,但在o'reilly mongo的书中,kristina说map reduce查询是您能做的最慢的事情之一,但它们也是最灵活和最可伸缩的。Mongo将能够分解查询并处理所有节点的处理能力,这意味着您应该通过添加的每个节点获得线性可伸缩性。但是在单个节点上,即使是group by查询也比map REDUCT快。另一个原因是mongodb的javascript引擎存在问题,它只允许它们使用一个线程。
Mongodb计划切换到google的v8 javascript引擎,希望它能让Mongodb处理map/reduce多线程。请参阅和如果可以,您应该查看聚合框架命令。虽然不如MapReduce灵活,但性能令人印象深刻。我使用它将大量收集的数据汇总成每小时、每天、每月的摘要,在我们的情况下,MapReduce的性能比超过1:50 我们选择了一种具有相同结构的分段集合的设计,它允许我们运行小而多的聚合作业,聚合命令的管道概念非常有效
我还发现$group命令的性能非常好,但是大小和碎片限制了它的使用 正如马特所说。当map reduce操作的空间需求超过可用内存量时,我会更关注mongo map reduce。它们包括创建和填充一个临时集合来创建结果(并在javascript中执行),它们将比JVM上的直接计算慢很多。感谢您的回复!关于下面的jira,我得出了相同的结论,据报道使用mongo的map reduce的性能比python差350倍:这里的答案是相同的:显然MongoDB map reduce仍然运行单线程。难怪它不能伸缩。它并不是真正意义上的map-reduce,而是高度并行的。