2010-04-08 14 views
27

Después de escuchar tantas cosas buenas sobre el rendimiento de MongoDB, decidimos probar Mongodb para resolver un problema que tenemos. Empecé moviendo todos los registros que tenemos en varias bases de datos de MySQL a una única colección en mongodb. Esto dio como resultado una colección con 29 millones de documentos (cada uno de ellos tiene al menos 20 campos) que ocupa alrededor de 100 GB de espacio en HD. Decidimos ponerlos todos en una sola colección, ya que todos los documentos tienen la misma estructura y queremos consultar y agregar resultados en todos esos documentos.El rendimiento de MongoDB en las consultas de agregación

Creé algunos índices para que coincidan con mis consultas, de lo contrario, incluso un conteo simple() llevaría años. Sin embargo, las consultas como distinct() y group() aún toman demasiado tiempo.

Ejemplo:

// creation of a compound index  
db.collection.ensureIndex({'metadata.system':1, 'metadata.company':1}) 

// query to get all the combinations companies and systems 
db.collection.group({key: { 'metadata.system':true, 'metadata.company':true }, reduce: function(obj,prev) {}, initial: {} }); 

Me tomó un vistazo al registro de mongod y tiene una gran cantidad de líneas como éstas (durante la ejecución de la consulta anterior):

Thu Apr 8 14:40:05 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1048890 nreturned:417 154ms 
Thu Apr 8 14:40:08 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1050205 nreturned:414 430ms 
Thu Apr 8 14:40:18 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1049748 nreturned:201 130ms 
Thu Apr 8 14:40:27 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1051925 nreturned:221 118ms 
Thu Apr 8 14:40:30 getmore database.collection cid:973023491046432059 ntoreturn:0 query: {} bytes:1053096 nreturned:250 164ms 
... 
Thu Apr 8 15:04:18 query database.$cmd ntoreturn:1 command reslen:4130 1475894ms 

Esta consulta se llevó 1475894ms cuales es mucho más larga de lo que esperaría (la lista de resultados tiene alrededor de 60 entradas). En primer lugar, ¿se espera esto dada la gran cantidad de documentos en mi colección? ¿Se espera que las consultas de agregación en general sean tan lentas en mongodb? ¿Alguna idea sobre cómo puedo mejorar el rendimiento?

Estoy ejecutando mongod en una sola máquina con un núcleo dual y 10 GB de memoria.

Gracias.

+1

Bueno, esta pregunta es demasiado antigua y todavía llega a los motores de búsqueda cuando se busca el marco de agregación MongoDB. Mario no mencionaste tu versión de MongoDB, porque mejoraron mucho el AF en 2.4 y lo estoy haciendo en un m1 horrible. EC2 con una memoria de 3.7G en una colección con 69m y es mucho más rápido de lo que solía ser. ¿Has probado la nueva versión o te has ido con un enfoque diferente? Seguro que hay muchos puntos de referencia para AF frente a MapReduce, pero eche un vistazo a la última de 10Gen http://blog.mongodb.org/post/62900213496/qaing-new-code-with-mms-map-reduce-vs -aggregation tnx – Maziyar

+0

Gracias por su comentario. Esto fue en 2010, creo que estábamos usando algo como MongoDB 1.4.0. Ha pasado un tiempo, estoy seguro de que muchas cosas han cambiado en mongodb desde entonces, pero no he estado trabajando en ese proyecto desde ese año :) –

+0

Gracias Mario por la respuesta. Acabo de empezar a utilizar MongoDB (alrededor de un año) y me preguntaba qué sucedió con tu proyecto. Buena suerte de todos modos :) – Maziyar

Respuesta

22

La idea es mejorar el rendimiento de las consultas de agregación utilizando MapReduce en una base de datos fragmentada que se distribuye en varias máquinas.

Hice algunas comparaciones del rendimiento de Mapreduce de Mongo con una declaración de grupo por select en Oracle en la misma máquina. Encontré que Mongo era aproximadamente 25 veces más lento. Esto significa que tengo que fragmentar los datos en al menos 25 máquinas para obtener el mismo rendimiento con Mongo que Oracle entrega en una sola máquina. Usé una colección/tabla con aproximadamente 14 millones de documentos/filas.

Exportar los datos de mongo a través de mongoexport.exe y usar los datos exportados como una tabla externa en Oracle y hacer un grupo por en Oracle fue mucho más rápido que usar el propio MapReduce de Mongo.

+0

Sería realmente útil saber qué versión de MongoDB. – nilskp

+0

Creo que era algo así como la versión 1.4.0. Esto fue en el año 2010. –

4

La agregación (map reduce o no) es muy lenta en mongo porque la realiza la máquina virtual JavaScript, no el motor de la base de datos. Esto sigue siendo una limitación de esto (muy bueno, imo) db para los datos de series de tiempo.

+1

Desde v2.2, la canalización de agregación usa [operaciones nativas] (http://docs.mongodb.org/manual/core/aggregation-introduction/#aggregation-pipelines). – Tamlyn

8

Un par de cosas.

1) Su consulta de grupo está procesando lotes de datos. Si bien su conjunto de resultados es pequeño, parece que está haciendo una escala de tabla de todos los datos en su colección para generar ese pequeño resultado. Esta es probablemente la causa raíz de la lentitud. Para acelerar esto, es posible que desee ver el rendimiento del disco de su servidor a través de iostat mientras la consulta se está ejecutando, ya que es probable que sea el cuello de botella.

2) Como se ha señalado en otras respuestas, el comando de grupo utiliza el intérprete de JavaScript, que limitará el rendimiento. Puede intentar usar el nuevo marco de agregación que se publica como beta en 2.1 (nota: esta es una versión inestable desde el 24 de febrero de 2012). Ver http://blog.mongodb.org/post/16015854270/operations-in-the-new-aggregation-framework para una buena introducción.Esto no solucionará el problema del volumen de datos en (1), pero se implementa en C++ y si el tiempo de JavaScript es el cuello de botella, entonces debería ser mucho más rápido.

3) Otro enfoque sería usar incrementos incrementales de mapas para generar una segunda colección con los resultados agrupados. La idea es ejecutar un trabajo de reducción de mapa para agregar los resultados una vez, y luego ejecutar periódicamente otro trabajo de reducción de mapa que vuelva a reducir los datos nuevos en la colección existente. Luego puede consultar esta segunda colección desde su aplicación en lugar de ejecutar un comando grupal todo el tiempo.

Cuestiones relacionadas