Il tuo problema di prestazioni osservato su una query iniziale è probabilmente uno dei seguenti problemi (in ordine approssimativo di probabilità):
1) La tua applicazione/servizio web ha un sovraccarico da inizializzare alla prima richiesta (ad esempio allocazione di memoria, configurazione di pool di connessioni, risoluzione di DNS, ...).
2) Gli indici oi dati che hai richiesto non sono ancora in memoria, quindi devono essere caricati.
3) Il Query Optimizer potrebbe richiedere un po' più di tempo per l'esecuzione alla prima richiesta, poiché sta confrontando l'esecuzione del piano per il modello di query.
Sarebbe molto utile testare la query tramite mongo
shell e isolare se l'overhead è correlato a MongoDB o al tuo servizio web (piuttosto che cronometrare entrambi, come hai fatto).
Di seguito sono riportate alcune note relative a MongoDB.
Memorizzazione nella cache
MongoDB non ha un tempo di "caching" per i documenti in memoria. Utilizza file mappati in memoria per l'I/O del disco e i documenti in memoria si basano sulle query attive (documenti/indici caricati di recente) e sulla memoria disponibile. Il gestore della memoria virtuale del sistema operativo è responsabile della caching e in genere seguirà un algoritmo LRU (Least-Recently Used) per decidere quali pagine scambiare fuori dalla memoria.
Utilizzo della memoria
Il comportamento previsto è che nel tempo MongoDB crescerà per utilizzare tutta la memoria libera per archiviare il tuo set di dati di lavoro attivo.
Guardando il tuo db.stats()
fornito numeri (e supponendo che sia il tuo solo database), sembra che la dimensione del tuo database sia di circa 1 Gb, quindi dovresti essere in grado di mantenere tutto all'interno della tua RAM totale di 10 Gb a meno che:
- ci sono altri processi in competizione per la memoria
- hai riavviato il tuo
mongod
server e quei documenti/indici non sono stati ancora richiesti
In MongoDB 2.2 è presente un nuovo touch
comando che puoi utilizzare per caricare indici o documenti in memoria dopo il riavvio del server. Questo dovrebbe essere utilizzato solo all'avvio iniziale per "riscaldare" il server, altrimenti potresti forzare inutilmente i dati "attivi" effettivi fuori dalla memoria.
Su un sistema Linux, ad esempio, puoi usare il top
comando e dovrebbe vedere che:
- Byte virtuali/VSIZE tenderanno ad essere la dimensione dell'intero database
- se il server non ha altri processi in esecuzione, i byte residenti/RSIZE saranno la memoria totale della macchina (questo include il contenuto della cache del file system)
mongod
non dovrebbe usare lo scambio (poiché i file sono mappati in memoria)
Puoi utilizzare mongostat
strumento per visualizzare rapidamente il tuo mongod
attività .. o più utile, usa un servizio come MMS
per monitorare le metriche nel tempo.
Ottimizzatore query
Il Query Optimizer
di MongoDB confronta l'esecuzione del piano per un modello di query ogni circa 1.000 operazioni di scrittura, quindi memorizza nella cache il piano di query "vincente" fino alla successiva esecuzione dell'ottimizzatore .. oppure chiami esplicitamente un explain()
su quella domanda.
Questo dovrebbe essere semplice da testare:esegui la tua query in mongo
shell con .explain()
e guarda i tempi di ms, e anche il numero di voci di indice e documenti scansionati. La tempistica per una spiegazione() non è il tempo effettivo necessario per l'esecuzione delle query, poiché include il costo del confronto dei piani. L'esecuzione tipica sarà molto più veloce .. e puoi cercare query lente nel tuo mongod
registro.
Per impostazione predefinita MongoDB registrerà tutte le query più lente di 100 ms, quindi questo fornisce un buon punto di partenza per cercare le query da ottimizzare. Puoi regolare il valore del ms lento con --slowms
config o utilizzando Database Profiler
comandi.
Ulteriori letture nella documentazione di MongoDB:
- Memorizzazione nella cache
- Controllo dell'utilizzo della memoria del server
- Profilatore database
- Spiega
- Monitoraggio e diagnostica