Uw waargenomen prestatieprobleem bij een eerste zoekopdracht is waarschijnlijk een van de volgende problemen (in ruwe volgorde van waarschijnlijkheid):
1) Uw applicatie / webservice heeft wat overhead om op eerste verzoek te initialiseren (d.w.z. geheugen toewijzen, verbindingspools opzetten, DNS oplossen, ...).
2) Indexen of gegevens die u hebt opgevraagd, bevinden zich nog niet in het geheugen, dus moeten worden geladen.
3) De Query Optimizer kan bij het eerste verzoek wat langer duren, omdat het de uitvoering van het plan vergelijkt voor uw querypatroon.
Het zou erg handig zijn om de zoekopdracht te testen via de mongo
shell, en isoleer of de overhead gerelateerd is aan MongoDB of uw webservice (in plaats van beide te timen, zoals u hebt gedaan).
Hieronder volgen enkele opmerkingen met betrekking tot MongoDB.
Caching
MongoDB heeft geen "caching"-tijd voor documenten in het geheugen. Het maakt gebruik van in het geheugen toegewezen bestanden voor schijf-I/O en de documenten in het geheugen zijn gebaseerd op uw actieve zoekopdrachten (documenten/indexen die u onlangs hebt geladen) en het beschikbare geheugen. De virtuele geheugenbeheerder van het besturingssysteem is verantwoordelijk voor caching , en zal doorgaans een Least-Recently Used (LRU)-algoritme volgen om te beslissen welke pagina's het geheugen moet verwisselen.
Geheugengebruik
Het verwachte gedrag is dat MongoDB na verloop van tijd zal groeien om al het vrije geheugen te gebruiken om uw actieve werkgegevensset op te slaan.
Kijkend naar uw verstrekte db.stats()
nummers (en ervan uitgaande dat dit uw enige is database), lijkt het erop dat uw database momenteel ongeveer 1 Gb is, dus u zou alles binnen uw totale RAM van 10 Gb moeten kunnen houden, tenzij:
- er zijn andere processen die strijden om geheugen
- je hebt je
mongod
opnieuw opgestart server en die documenten/indexen zijn nog niet opgevraagd
In MongoDB 2.2 is er een nieuwe touch
opdracht die u kunt gebruiken om indexen of documenten in het geheugen te laden nadat de server opnieuw is opgestart. Dit mag alleen worden gebruikt bij de eerste keer opstarten om de server "op te warmen", omdat u anders de werkelijke "actieve" gegevens uit het geheugen zou kunnen forceren.
Op een Linux-systeem kunt u bijvoorbeeld de top
. gebruiken commando en zou dat moeten zien:
- virtuele bytes/VSIZE hebben de neiging om de grootte van de hele database te hebben
- als de server geen andere processen heeft lopen, zullen residente bytes/RSIZE het totale geheugen van de machine zijn (inclusief de inhoud van de cache van het bestandssysteem)
mongod
mag geen swap gebruiken (aangezien de bestanden in het geheugen zijn toegewezen)
U kunt de mongostat
gebruiken
tool om snel een beeld te krijgen van je mongod
activiteit .. of handiger, gebruik een service zoals MMS
om statistieken in de loop van de tijd te volgen.
Query Optimizer
De MongoDB Query Optimizer
vergelijkt de uitvoering van het plan voor een querypatroon elke ~ 1.000 schrijfbewerkingen, en slaat vervolgens het "winnende" queryplan in de cache op tot de volgende keer dat de optimizer wordt uitgevoerd .. of u roept expliciet een explain()
op die vraag.
Dit zou eenvoudig moeten zijn om te testen:voer uw zoekopdracht uit in de mongo
shell met .explain()
en kijk naar de MS-timings, en ook het aantal indexitems en gescande documenten. De timing voor een explain() is niet de werkelijke tijd die nodig is om de query's uit te voeren, aangezien de kosten voor het vergelijken van de plannen zijn inbegrepen. De typische uitvoering zal veel sneller zijn .. en je kunt zoeken naar langzame zoekopdrachten in je mongod
logboek.
Standaard registreert MongoDB alle query's die langzamer zijn dan 100 ms, dus dit biedt een goed startpunt om te zoeken naar te optimaliseren query's. U kunt de trage ms-waarde aanpassen met de --slowms
config-optie, of gebruik de Database Profiler
commando's.