¿Es el marco de agregación de Mongodb más rápido que map / reduce?

¿El marco de agregación introducido en mongodb 2.2 tiene alguna mejora de rendimiento especial sobre map / reduce?

Si es así, ¿por qué, cómo y cuánto?

(Ya he hecho una prueba por mí mismo, y el rendimiento fue casi el mismo)

Cada prueba que he ejecutado personalmente (incluido el uso de sus propios datos) muestra que el marco de agregación es un múltiplo más rápido que la reducción del mapa, y por lo general es un orden de magnitud más rápido.

Simplemente tomando la décima parte de los datos que publicó (pero en lugar de borrar el caché del sistema operativo, calentar primero el caché, porque quiero medir el rendimiento de la agregación y no cuánto tiempo lleva ingresar los datos) Obtuve esto:

MapReduce: 1,058ms
Marco de agregación: 133 ms

Eliminar el $ match del framework de agregación y {query:} de mapReduce (porque ambos solo usarían un índice y eso no es lo que queremos medir) y agrupar todo el conjunto de datos por key2 Obtuve:

MapReduce: 18.803 ms
Marco de agregación: 1,535 ms

Esos están muy en línea con mis experimentos previos.

Mi punto de referencia:

== Generación de datos ==

Generar 4 millones de filas (con python) fácil con aproximadamente 350 bytes. Cada documento tiene estas claves:

  • key1, key2 (dos columnas aleatorias para probar la indexación, una con cardinalidad de 2000 y una con cardinalidad de 20)
  • longdata: una cadena larga para boost el tamaño de cada documento
  • valor: un número simple (const 10) para probar la agregación

 db = Connection('127.0.0.1').test # mongo connection random.seed(1) for _ in range(2): key1s = [hexlify(os.urandom(10)).decode('ascii') for _ in range(10)] key2s = [hexlify(os.urandom(10)).decode('ascii') for _ in range(1000)] baddata = 'some long date ' + '*' * 300 for i in range(2000): data_list = [{ 'key1': random.choice(key1s), 'key2': random.choice(key2s), 'baddata': baddata, 'value': 10, } for _ in range(1000)] for data in data_list: db.testtable.save(data) 

El tamaño total de los datos fue de aproximadamente 6 GB en mongo. (y 2GB en postgres)

== Pruebas ==

Hice algunas pruebas, pero una es suficiente para comparar los resultados:

NOTA: El servidor se reinicia y la memoria caché del sistema operativo se limpia después de cada consulta para ignorar el efecto del almacenamiento en caché.

CONSULTA: agrega todas las filas con key1=somevalue (alrededor de 200K filas) y sum el value de cada key2

  • mapa / reducir 10.6 segundos
  • aggreate 9.7 segundos
  • grupo 10.3 sec

consultas:

mapreduce:

db.testtable.mapReduce(function(){emit(this.key2, this.value);}, function(key, values){var i =0; values.forEach(function(v){i+=v;}); return i; } , {out:{inline: 1}, query: {key1: '663969462d2ec0a5fc34'} })

agregar:

db.testtable.aggregate({ $match: {key1: '663969462d2ec0a5fc34'}}, {$group: {_id: '$key2', pop: {$sum: '$value'}} })

grupo:

db.testtable.group({key: {key2:1}, cond: {key1: '663969462d2ec0a5fc34'}, reduce: function(obj,prev) { prev.csum += obj.value; }, initial: { csum: 0 } })