2011-09-06 24 views
7

Soy relativamente novato en MongoDB, pero por lo que he leído hay varios métodos para encontrar promedios y sumas de valores en una base de datos MongoDB, con varios beneficios y desventajas para cada uno.'AVG' y la funcionalidad 'SUM' en MongoDB, ¿algún consejo?

Estoy principalmente pidiendo un método para encontrar la suma de una selección de valores, y la media de una selección de valores, en un método tan eficiente (rápido) como sea posible.

Los documentos de la colección que se está consultando asemejan a esta estructura (con una gran cantidad de otros campos):

{ 
    "_id": ObjectId('4e650107580fd649e5000005'), 
    "date_added": ISODate("2011-09-05T00:00:00Z"), 
    "value": 1500 
} 

puede calcular previamente cosas como sumas es, en mi solicitud, no siempre es posible, ya que la selección de valores para Sumarse puede cambiar (en función de los intervalos de fechas, por ejemplo, entre una fecha de inicio y una fecha de finalización, cuál es el promedio). Este es un problema similar con promedios precalculados.

Por lo que he leído, MapReduce definitivamente no es ideal para la búsqueda en tiempo real (es decir, a pedido), por lo que parece estar fuera de cuestión también.

En este momento estoy consultando la colección de esta manera: (Nota: esto es usar pymongo)

response = request.db['somecollection'].find(
    { 
     'date_added': { 
      '$gte': date_start, 
      '$lte': date_end 
     } 
    }, 
    { 
     'value':1 
    } 
).limit(500) 

Entonces se hizo el cálculo en Python usando un bucle for sobre la respuesta. El límite de 500 resultados es arbitrario, para evitar que se vuelva demasiado lento. Solo estoy recuperando el valor y ninguno de los otros campos.

¿Es este el método más eficiente de hacer este cálculo, o hay otros métodos para lograr lo que necesito?

Advertencias:

  • No puedo usar la función group porque probablemente va a utilizar en el futuro sharding
  • no puedo usar MapReduce porque es una función que se utiliza en -la marcha por los usuarios
  • no puedo precalcular muchos de mis sumas/medias debido a que la selección de valores para resumir/media es casi siempre diferente
  • he mirado alrededor stackoverflow y la web para tratar de encontrar recomendaciones sobre la manera de hacer este tipo de cosas, y es bastante abierto-

EDIT:

Debo señalar que el número de documentos de regresar de la consulta que he publicado anteriormente podría ser cualquier cosa de 1 documento a cientos, pero probablemente tendrá un número máximo de documentos devueltos de alrededor de 150 (promedio de alrededor de 60 o 70)

Respuesta

4

Dale un mapa: prueba un poco, probablemente no sea tan lento como crees. Lo he usado para la agregación en tiempo real sobre algunos conjuntos de datos grandes, y aunque a veces no es muy rápido, a menudo está bien. Es mejor si se puede filtrar por el tamaño de los datos iniciales que estás agregando, por ejemplo .:

db.collection.mapReduce(m, r, { query : { year: 2011 } }); 

Si necesita acelerar las cosas aún más, tenga en cuenta la distribución de los datos a través de un grupo fragmentada.Luego, el procesamiento de reducción de mapa se puede escalar a través de múltiples fragmentos que se ejecutan en paralelo.

+0

Definitivamente voy a experimentar más con MapReduce. Sé que va a variar entre conjuntos de datos/consultas/etc., pero en su caso fue lo suficientemente rápido como para no ser realmente notable para el usuario (es decir, menos de medio segundo)? – johneth

+0

Varía entre 500 y 5000 ms, pero algunos de los conjuntos de datos eran bastante grandes (más de 100 millones de documentos), por lo que necesitaban un indicador de ocupado/progreso, pero lo suficientemente rápido. El rendimiento de reducción de mapas también debería mejorar cuando el motor de JavaScript se actualiza desde SpiderMonkey de subproceso único a V8. –

+0

Ah, eso suena prometedor. Por el momento, mi conjunto de datos es muy pequeño (medido en miles, no en millones), aunque esto crecerá con el tiempo. – johneth

2

respuesta simple es:

  1. Si posible precalcular todo lo que puede precalcular.
  2. Si necesita datos agregados por rangos de fechas y la agregación debería funcionar lo más rápido posible, utilice map/reduce + sharding para distribuir el cálculo entre varias máquinas.

Pero en la misma guía mongodb tiempo dicen:

El precio de usar MapReduce es la velocidad: el grupo no es particularmente rápido, pero MapReduce es más lento y no se supone que se utilizará en “real time. "Ejecuta MapReduce como un trabajo en segundo plano, crea una colección de resultados y luego puede consultar esa colección en tiempo real .

Parece que mongodb no es la mejor solución para la agregación de datos en tiempo real.

+0

Definitivamente estoy calculando todos los valores que puedo. Lamentablemente, estoy confinado a una máquina, al menos al principio, por lo que no puedo distribuirla entre varias máquinas. En mi ejemplo, ¿la cantidad de documentos devueltos afecta la velocidad suficiente para considerar usar MapReduce? (Agregué la cantidad promedio de documentos devueltos al final de mi pregunta) – johneth

3

MongoDB señala

OK, así map/reduce y la agregación de tener algunos problemas serios actualmente.

Advertencia grande: la instancia de MongoDB solo puede tener una instancia de "motor de JavaScript". Esto significa que no puede ejecutar dos Map/Reduces simultáneos en el servidor. Y solo obtienes un núcleo para ejecutar el mapa -reduce.

En el caso de lo que estás haciendo, básicamente estás "rodando tu propio" M/R. La desventaja es el tráfico de red adicional. Lo bueno es que ahora puedes lanzar más núcleos al problema (desde los servidores web).

Su pregunta clave

No puedo precalcular muchos de mis sumas/medias debido a que la selección de valores para resumir/media es casi siempre diferente

No hay en general método para optimizar todas las consultas posibles. Si desea que el sistema pueda sumar y agregar a lo largo de cada campo para cada rango, eventualmente encontrará un conjunto de campos/rangos que son demasiado grandes.

La manera de "resolver" esto es reducir el conjunto de campos y rangos.

Así que mantenga los contadores diarios/por hora y sume esos contadores. Al menos, reduce el número de documentos que necesita escanear para responder a su consulta.

1

MongoDB está programado para obtener funciones de agregación nativas para cosas como suma/promedio/mínimo/máximo en la versión 2.1.1 (actualmente programada para el 1 de noviembre de 2011). Para obtener más detalles y estado, consulte el problema en: https://jira.mongodb.org/browse/SERVER-447

Cuestiones relacionadas