tuning sort optimize examples docs java performance mongodb mapreduce

sort - MongoDB MapReduce es mucho más lento que el puro procesamiento de Java?



mongoose aggregate function (3)

Quería contar todas las claves de mis documentos (incluidas las integradas) de una colección. Primero escribí un cliente Java para resolver esto. Tardó menos de 4 segundos para mostrar el resultado. Luego escribí una función de mapa / reducir. El resultado fue bueno, pero ejecutar la función tomó más de 30 segundos. Pensé que la función de mapa / reducir sería más rápida ya que se ejecuta en el lado del servidor. El cliente de Java necesita buscar todos los documentos del servidor pero, sin embargo, es mucho más rápido. ¿Por que es esto entonces?

// Aquí está mi función de mapa:

map = function(){ for(var key in this) { emit(key, {count:1}); if(isNestedObject(this[key])){ m_sub(key, this[key]); } } }

// Aquí está mi función de reducción:

reduce = function (key, emits) { total = 0; for (var i in emits) { total += emits[i].count; } return {count:total}; }

// Aquí está la llamada a 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]); } } } } })

// Aquí está el resultado:

{ "result" : "tmp.mr.mapreduce_1292252775_8", "timeMillis" : 39087, "counts" : { "input" : 20168, "emit" : 986908, "output" : 1934 }, "ok" : 1 }

// Aquí está mi cliente 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()); }

// Aquí está el resultado:

00:03:726 duration:3726 ms 1898

No se preocupe por la diferente cantidad de resultados (1934 vs. 1898). Esto se debe a que la reducción de mapa cuenta también las claves en la matriz que no cuentan los clientes de Java. Gracias por arrojar algo de luz sobre los diferentes tiempos de ejecución.


Esta no es una gran respuesta, pero en el libro de monly o''reilly, kristina dice que las consultas de reducción de mapas son una de las cosas más lentas que puedes hacer, pero también son las más flexibles y las más escalables. Mongo podrá separar la consulta y manejar la potencia de procesamiento en todos los nodos, lo que significa que debe obtener escalabilidad lineal con cada nodo que agregue. Pero en un solo nodo, incluso un grupo por consulta será más rápido que el mapa de reducir.



Si puede, debe ver el comando aggregation framework. No es tan flexible como MapReduce, pero el rendimiento es impresionante. Lo utilicé para agregar una gran cantidad de datos de colecciones a resúmenes mensuales, diarios y por hora; la relación de rendimiento con MapReduce fue de más de 1 a 50 en nuestra situación.

Optamos por un diseño con una colección segmentada con una estructura idéntica que nos permitiera ejecutar trabajos de agregación pequeños pero numerosos, el concepto de canalización del comando de agregación funciona muy bien.

También encontré que el comando $ group es muy eficiente, pero la limitación del tamaño y los fragmentos restringen su uso.