2015-02-06 27 views
24

Ho una collezione mongoDB con milioni di righe e sto cercando di ottimizzare le mie query. Attualmente sto usando il framework di aggregazione per recuperare i dati e raggrupparli come voglio. La mia tipica query di aggregazione è simile a: $match > $group > $ group > $project

Tuttavia, ho notato che le ultime parti richiedono solo pochi ms, l'inizio è il più lento.

Ho tentato di eseguire una query con solo il filtro di corrispondenza $ e quindi di eseguire la stessa query con collection.find. La query di aggregazione richiede ~ 80 ms mentre la query di ricerca impiega 0 o 1 ms.

Ho indici su praticamente ogni campo quindi immagino che questo non sia il problema. Qualche idea su cosa potrebbe andare storto? O è solo un "normale" svantaggio della struttura di aggregazione?

Potrei utilizzare le query di ricerca anziché le query di aggregazione, tuttavia dovrei eseguire molte elaborazioni dopo la richiesta e questo processo può essere eseguito rapidamente con $group ecc. Quindi preferirei mantenere il framework di aggregazione.

Grazie,

EDIT:

Ecco i miei criteri:

{ 
    "action" : "click", 
    "timestamp" : { 
      "$gt" : ISODate("2015-01-01T00:00:00Z"), 
      "$lt" : ISODate("2015-02-011T00:00:00Z") 
    }, 
    "itemId" : "5" 
} 
+0

Puoi pubblicare il tuo '$ match' e trovare?Nella maggior parte degli usi, un '$ match' e un find dovrebbero essere equivalenti, ma mi piacerebbe vedere esattamente quali dichiarazioni si stanno confrontando per ottenere una risposta precisa. Inoltre, hai prima eseguito l'aggregazione e poi la ricerca? Cosa succede se ripeti i due più e più volte e confronta i tempi? La differenza avrebbe potuto essere il costo di spostare i risultati in memoria dal disco. – wdberkeley

+0

Ho aggiunto i criteri al primo post, tuttavia anche senza i criteri di timestamp vedo un grosso gap. Ma ora mi chiedo se non è legato al fatto che find() restituisce un cursore e mostra solo i primi risultati. – Owumaro

+7

Ok, avevo un sacco di indici inutili, quindi ho pulito tutto e creato solo un indice composto (con i campi del mio filtro $ match). Ora ho buone prestazioni e stesse prestazioni per trovare e aggregare con $ match :) Problema risolto. – Owumaro

risposta

14

Lo scopo principale del aggregation framework è quello di facilitare la query di un grande numero di voci e di generare un numero basso di risultati che valgono per te.

Come hai detto, puoi anche utilizzare più query find, ma ricorda che non puoi creare nuovi campi con le query find. D'altra parte, la fase $group consente di definire i nuovi campi.

Se si desidera ottenere la funzionalità di aggregation framework, è molto probabile che sia necessario eseguire uno find iniziale (o raggrupparne diversi), estrarre tali informazioni e manipolarle ulteriormente con un linguaggio di programmazione.

Il aggregation pipeline potrebbe richiedere più tempo, ma almeno si sa che è necessario tenere conto delle prestazioni di un solo sistema: il motore MongoDB.

Considerando che, quando si tratta di manipolare i dati restituiti da una query find, è molto probabile che si debba manipolare ulteriormente i dati con un linguaggio di programmazione, aumentando così la complessità a seconda delle complessità del linguaggio di programmazione prescelto.

+9

Grazie per l'informazione. Tuttavia, non riesco ancora a capire perché una query aggregata con solo un filtro di corrispondenza $ non sia veloce come una semplice query di ricerca con lo stesso filtro. – Owumaro

3

Hai provato a utilizzare explain() per le query di ricerca? Ti darà un'idea di quanto tempo impiegherà esattamente la query find(). Puoi fare lo stesso per $ match con $ explain & vedi se c'è qualche differenza nell'indice che accede ad altri parametri &.

Anche la parte $ del quadro di aggregazione non utilizza l'indicizzazione, pertanto deve elaborare tutti i record restituiti dalla fase di corrispondenza $ del framework di aggregazione. Quindi per capire meglio il funzionamento della tua query vedi il set di risultati che restituisce & se può essere elaborato da MongoDB in memoria.