sql >> Database >  >> NoSQL >> MongoDB

Omgaan met trage zoekopdrachten in MongoDB

In productie moet een applicatie de gebruiker tijdig een reactie geven om de gebruikersinteractie met uw applicatie te verbeteren. Soms kunnen databasequery's echter achterblijven, waardoor er een langere latentie nodig is voordat een reactie de gebruiker bereikt, of liever gezegd, de doorvoerbewerking wordt beëindigd vanwege het overschrijden van de ingestelde gemiddelde time-out.

In deze blog gaan we leren hoe je deze problemen in MongoDB kunt identificeren, manieren om ze op te lossen wanneer ze zich voordoen en wat de mogelijke strategieën zijn die kunnen worden ondernomen zodat dit niet meer kan gebeuren.

P>

Vaak leidt dit tot trage reacties op zoekopdrachten door een verminderde CPU-capaciteit die de onderliggende werkset niet aankan. Werkset in dit geval is de hoeveelheid gegevens en indexen die worden onderworpen aan een doorvoerinstantie die op dat moment dus actief is. Hier wordt met name rekening mee gehouden bij capaciteitsplanning wanneer men verwacht dat de hoeveelheid gegevens die ermee gemoeid is in de loop van de tijd zal toenemen en het aantal gebruikers dat met uw platform bezig is, zal toenemen.

Een langzame query-probleem identificeren

Er zijn twee manieren waarop u trage zoekopdrachten in MongoDB kunt identificeren.

  1. De Profiler gebruiken
  2. Db.currentOp()-helper gebruiken

De MongoDB Profiler gebruiken

Databaseprofiler in MongoDB is een mechanisme voor het verzamelen van gedetailleerde informatie over databaseopdrachten die worden uitgevoerd tegen een actieve mongod-instantie, namelijk:doorvoerbewerkingen (maken, lezen, bijwerken en verwijderen) en de configuratie- en beheeropdrachten.

De profiler gebruikt een afgetopte verzameling met de naam system.profile waar alle gegevens worden weggeschreven. Dit betekent dat wanneer de collectie qua omvang vol is, de oudere documenten worden verwijderd om ruimte te maken voor nieuwe gegevens.

De Profiler is standaard uitgeschakeld, maar afhankelijk van het profileringsniveau kan men deze per database of per instantie inschakelen. De mogelijke profileringsniveaus zijn:

  • 0 - de profiler is uitgeschakeld en verzamelt daarom geen gegevens.
  • 1 - de profiler verzamelt gegevens voor bewerkingen die langer duren dan de waarde van slowms
  • 2- de profiler verzamelt gegevens voor alle bewerkingen.

 Het inschakelen van profilering heeft echter invloed op de prestaties van de database en het schijfgebruik, vooral wanneer het profileringsniveau is ingesteld op 2 . Men moet rekening houden met eventuele gevolgen voor de prestaties voordat u de profiler inschakelt en configureert voor een productie-implementatie.

Om de profilering in te stellen, gebruiken we de db.setProfilingLevel()-helper zoals:

db.setProfilingLevel(2)

Een voorbeelddocument dat wordt opgeslagen in de verzameling system.profile is:

{ "was" : 0, "slowms" : 100, "sampleRate" : 1.0, "ok" : 1 }

Het sleutel/waarde-paar "ok":1 geeft aan dat de bewerking is geslaagd, terwijl slowms de drempeltijd in milliseconden is die een bewerking zou moeten duren en standaard 100 ms is.

Deze waarde wijzigen

db.setProfilingLevel(1, { slowms: 50 })

Zoeken naar gegevens tegen de verzamelingsrun van system.profile:

db.system.profile.find().pretty()

Db.currentOp()helper gebruiken

Deze functie geeft een overzicht van de huidige lopende query's met zeer gedetailleerde informatie, zoals hoe lang ze al zijn uitgevoerd. Op een draaiende mongo-shell voer je de opmerking bijvoorbeeld uit:

db.currentOp({“secs_running”:{$gte:5}}) 

Waarbij secs_running de filterstrategie is, zodat alleen bewerkingen die meer dan 5 seconden hebben geduurd, worden geretourneerd, waardoor de uitvoer wordt verminderd. Dit wordt vaak gebruikt wanneer de gezondheid van de CPU 100% kan worden beoordeeld vanwege de nadelige invloed die dit kan hebben op de database. Dus door de waarden te wijzigen, leert u welke query's lang duren om uit te voeren.

De geretourneerde documenten hebben de volgende sleutels:

  • query :wat de vraag inhoudt
  • actief : als de zoekopdracht nog bezig is.
  • ns :collectienaam waartegen de query moet worden uitgevoerd
  • secs_running :  duur van de zoekopdracht tot nu toe in seconden

Door aan te geven welke zoekopdrachten lang duren, heb je vastgesteld wat de CPU overbelast.

Resultaten interpreteren en problemen oplossen

 Zoals we hierboven hebben beschreven, is de latentie van zoekopdrachten erg afhankelijk van de hoeveelheid gegevens die ermee gemoeid zijn, wat anders tot inefficiënte uitvoeringsplannen zal leiden. Dit wil zeggen dat als u bijvoorbeeld geen indexen in uw verzameling gebruikt en bepaalde records wilt bijwerken, de bewerking alle documenten moet doorlopen in plaats van alleen te filteren op die documenten die overeenkomen met de queryspecificatie. Logischerwijs duurt dit langer, wat leidt tot een trage zoekopdracht. U kunt een inefficiënt uitvoeringsplan onderzoeken door het volgende uit te voeren:Explain('executionStats') dat statistieken biedt over de prestaties van de query. Vanaf dit punt kunt u leren hoe de query de index gebruikt, naast het geven van een aanwijzing of de index optimaal is.

Als de uitleg-helper terugkeert

{

   "queryPlanner" : {

         "plannerVersion" : 1,

         ...

         "winningPlan" : {

            "stage" : "COLLSCAN",

            ...

         }

   },

   "executionStats" : {

      "executionSuccess" : true,

      "nReturned" : 3,

      "executionTimeMillis" : 0,

      "totalKeysExamined" : 0,

      "totalDocsExamined" : 10,

      "executionStages" : {

         "stage" : "COLLSCAN",

         ...

      },

      ...

   },

   ...

}

queryPlanner.winningPlan.stage:COLLSCAN-sleutelwaarde geeft aan dat de mongod het hele incassodocument moest scannen om de resultaten te identificeren, daarom wordt het een dure operatie en leidt het tot trage zoekopdrachten.

executionStats.totalKeysExamined:0 betekent dat de collectie geen indexeringsstrategie gebruikt

Voor een bepaalde zoekopdracht moet het aantal betrokken documenten bijna nul zijn. Als het aantal documenten vrij groot is, zijn er twee mogelijkheden:

  1. Indexering niet gebruiken met de collectie
  2. Een index gebruiken die niet optimaal is.

Als u een index voor een verzameling wilt maken, voert u de opdracht uit: 

db.collection.createIndex( { quantity: 1 } )

Waar kwantiteit een voorbeeldveld is dat u hebt geselecteerd om optimaal te zijn voor de indexeringsstrategie.

Als je meer wilt weten over indexeren en welke indexeringsstrategie je moet gebruiken, kijk dan op deze blog

Conclusie

De achteruitgang van de databaseprestaties kan gemakkelijk worden weergegeven door langzame zoekopdrachten te hebben, wat de minste verwachting is die platformgebruikers zouden verwachten. Men kan trage zoekopdrachten in MongoDB identificeren door de profiler in te schakelen en deze te configureren volgens zijn specificaties of door db.currentOp() uit te voeren op een draaiende mongod-instantie.

Door naar de tijdparameters op het geretourneerde resultaat te kijken, kunnen we identificeren welke query's achterblijven. Nadat we deze zoekopdrachten hebben geïdentificeerd, gebruiken we de helper voor deze zoekopdrachten om meer details te krijgen, bijvoorbeeld als de zoekopdracht een index gebruikt.

Zonder indexering worden de bewerkingen duur omdat er veel documenten moeten worden gescand voordat de wijzigingen worden toegepast. Met deze tegenslag zal de CPU overbelast raken, wat resulteert in langzame query's en stijgende CPU-pieken.

De grootste fout die tot langzame query's leidt, is een inefficiënte uitvoeringsplanning die eenvoudig kan worden opgelost door een index met de betrokken verzameling te gebruiken.


  1. MongoDB Node controleren of object-id geldig is

  2. Spring Data Reactive Repositories met MongoDB

  3. Schijfgebruik van een Docker-container analyseren

  4. Is het veilig om het journaalbestand van mongodb te verwijderen?