2011-09-06 10 views
7

Sono un novizio relativo a MongoDB, ma da quello che ho letto ci sono vari metodi per trovare medie e somme di valori in un database MongoDB, con vari vantaggi e svantaggi per ciascuno.Funzionalità 'AVG' e 'SUM' in MongoDB, qualche consiglio?

Sto principalmente chiedendo un metodo per trovare la somma di una selezione di valori e la media di una selezione di valori, in un metodo efficiente (veloce) possibile.

I documenti della collezione interrogato assomigliano tale struttura (con un sacco di altri campi):

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

precalcolato cose come somme è, nella mia domanda, non sempre è possibile, perché la selezione di valori essere sommato può cambiare (in base agli intervalli di date, ad esempio tra una data di inizio e una data di fine, qual è la media). Questo è un problema simile con le medie di calcolo preliminare.

Da quello che ho letto, MapReduce non è sicuramente l'ideale per la ricerca in tempo reale (cioè su richiesta), quindi sembra essere fuori discussione anche tu.

Al momento mi sto interrogando la raccolta in questo modo: (Nota: Questo sta usando pymongo)

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

Poi facendo il calcolo in Python utilizzando un ciclo for sopra la risposta. Il limite di 500 risultati è arbitrario, per evitare che diventi troppo lento. Sto solo recuperando il valore e nessuno degli altri campi.

È questo il metodo più efficiente per eseguire questo calcolo o esistono altri metodi per eseguire ciò che mi serve?

Avvertenze:

  • non posso utilizzare la funzione group perché io probabilmente utilizzerò sharding in futuro
  • Non posso usare MapReduce perché è una funzione che verrà utilizzato su -the-fly dagli utenti
  • Non riesco a calcolare molto le mie somme/medie perché la selezione dei valori per somma/media è quasi sempre diversa
  • Mi sono guardato attorno allo stackoverflow e al web per provare trovare raccomandazione su come fare questo genere di cose, ed è abbastanza indeterminato

EDIT:

Tengo a precisare che il numero di documenti restituiti dalla query che ho postato qui sopra potrebbe essere qualsiasi cosa da 1 documento a centinaia, ma probabilmente avrà un numero massimo di documenti restituiti di circa 150 (media di circa 60 o 70)

risposta

4

Dai alla mappa una prova, probabilmente non è così lento come pensi. L'ho usato per l'aggregazione in tempo reale su alcuni set di dati di grandi dimensioni e, anche se a volte non è fulmineo, va più spesso bene. E 'meglio se si può filtrare verso il basso la dimensione dei dati iniziali si sta aggregando, per es .:

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

Se è necessario accelerare le cose ancora di più, prendere in considerazione la distribuzione dei dati attraverso un cluster sharded.Quindi l'elaborazione di riduzione della mappa può essere ridimensionata su più frammenti in parallelo.

+0

Sto sicuramente sperimentando di più con MapReduce. So che varierà tra i dataset/query/ecc., Ma nel tuo caso è stato abbastanza veloce da non essere realmente visibile all'utente (cioè meno di mezzo secondo)? – johneth

+0

Variabile tra 500-5000 ms, ma alcuni set di dati erano piuttosto grandi (100 M + doc), quindi era necessario un indicatore di occupato/progresso, ma abbastanza veloce. Le prestazioni di riduzione della mappa dovrebbero anche migliorare quando il motore JavaScript viene aggiornato da SpiderMonkey a thread singolo a V8. –

+0

Ah, sembra promettente. Al momento il mio set di dati è molto piccolo (misurato in migliaia, non in milioni), anche se questo crescerà nel tempo. – johneth

2

risposta è semplice:

  1. Se possibile precalculate tutto ciò che si può precalculate.
  2. Se sono necessari dati aggregati per intervalli di date e l'aggregazione dovrebbe funzionare il più rapidamente possibile, utilizzare map/reduce + sharding per distribuire il calcolo su più macchine.

Ma nella stessa guida MongoDB tempo dicono:

Il prezzo di utilizzo di MapReduce è la velocità: gruppo non è particolarmente veloce, ma MapReduce è più lento e non dovrebbe essere utilizzato in “reale tempo. "Si esegue MapReduce come lavoro in background, si crea una raccolta di risultati e quindi è possibile richiedere tale raccolta in tempo reale .

Quindi sembra che mongodb non sia la soluzione migliore per l'aggregazione dei dati in tempo reale.

+0

Definisco definitivamente tutti i valori possibili. Sfortunatamente sono limitato a una macchina, almeno all'inizio, quindi non posso diffonderlo su più macchine. Nel mio esempio, il numero di documenti restituiti influisce sulla velocità sufficiente per considerare l'utilizzo di MapReduce? (Ho aggiunto il numero medio di documenti restituiti in fondo alla mia domanda) – johneth

3

MongoDB note

OK, quindi Map/Reduce e aggregazione avere alcuni seri problemi al momento.

Grande avvertenza: l'istanza MongoDB può avere solo un'istanza "motore javascript". Ciò significa che non è possibile eseguire due Map/Reduces simultanei sul server. E ottieni solo un core per l'esecuzione della mappa: riduci.

Nel caso di ciò che si sta facendo, si sta fondamentalmente "rotolando il proprio" M/R. Lo svantaggio è il traffico di rete extra. Il vantaggio è che ora puoi lanciare più core sul problema (dai server web).

tua domanda chiave

Non posso precalculate un sacco di miei somme/medie perché la selezione dei valori per riassumere/media è quasi sempre diversa

Non v'è alcun generale metodo per ottimizzare "tutte le possibili" richieste. Se si desidera che il sistema sia in grado di sommare e aggregare lungo ogni campo per ogni intervallo, alla fine si troverà un insieme di campi/intervalli troppo grandi.

Il modo per "risolvere" questo è ridurre l'insieme di campi e intervalli.

Quindi mantieni contatori giornalieri/orarie e somma su quei contatori. Almeno riduci il numero di documenti che devi scannerizzare per rispondere alla tua domanda.

1

MongoDB è previsto per ottenere funzioni di aggregazione native per cose come sum/avg/min/max nella versione 2.1.1 (attualmente previsto per il 1 ° novembre 2011). Per maggiori dettagli e stato, consultare il problema: https://jira.mongodb.org/browse/SERVER-447

Problemi correlati