sql >> Databasteknik >  >> NoSQL >> MongoDB

Hantera långsamma frågor i MongoDB

När den är i produktion bör en applikation ge ett snabbt svar till användaren i syfte att förbättra användarinteraktionen med din applikation. Ibland kan databasförfrågningar dock börja släpa och därför ta en längre latens för ett svar att nå användaren eller snarare att genomströmningsoperationen avbröts på grund av att den inställda genomsnittliga timeouten överträffades.

I den här bloggen kommer vi att lära oss hur du kan identifiera dessa problem i MongoDB, sätt att åtgärda dem när de uppstår och vilka strategier som är möjliga att vidta så att detta inte kan hända igen.

Oftare är det som leder till långsamma frågesvar försämrad CPU-kapacitet som inte kan motstå den underliggande arbetsuppsättningen. Arbetsuppsättningen i det här fallet är mängden data och index som kommer att utsättas för en genomströmningsinstans som alltså är aktiv i det ögonblicket. Detta beaktas särskilt vid kapacitetsplanering när man förväntar sig att mängden inblandad data ska öka med tiden och antalet användare som engagerar sig i din plattform.

Identifiera ett långsamt frågeproblem

Det finns två sätt att identifiera långsamma frågor i MongoDB.

  1. Använda Profiler
  2. Använda db.currentOp() helper

Använda MongoDB Profiler

Databasprofilerare i MongoDB är en mekanism för att samla in detaljerad information om databaskommandon som körs mot en körande mongod-instans som är:genomströmningsoperationer (Skapa, Läs, Uppdatera och Ta bort) och kommandon för konfiguration och administration.

Profileraren använder en begränsad samling som heter system.profile där den skriver all data. Detta innebär att när samlingen är full storleksmässigt raderas de äldre dokumenten för att ge utrymme för nya data.

Profiler är avstängd som standard, men beroende på profileringsnivå kan man aktivera den per databas eller per instans. De möjliga profileringsnivåerna är:

  • 0 - profileraren är avstängd och samlar därför inte in någon data.
  • 1 - profileraren samlar in data för operationer som tar längre tid än värdet av långsammare
  • 2- profileraren samlar in data för alla operationer.

 Men att aktivera profilering genererar en prestandapåverkan på databasen och diskanvändningen, särskilt när profileringsnivån är inställd på 2 . Man bör överväga eventuella prestandaimplikationer innan man aktiverar och konfigurerar profileraren på en produktionsinstallation.

För att ställa in profileringen använder vi db.setProfilingLevel()-hjälpen som:

db.setProfilingLevel(2)

Ett exempeldokument som kommer att lagras i system.profile-samlingen kommer att vara:

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

Nyckel-värdeparet "ok":1 indikerar att operationen lyckades medan långsammare är tröskeltiden i millisekunder som en operation bör ta och som standard är 100ms.

För att ändra detta värde

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

För att fråga efter data mot system.profile-samlingskörningen:

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

Använda db.currentOp()helper

Denna funktion listar de aktuella sökfrågorna med mycket detaljerad information som hur länge de har körts. På ett löpande mongo-skal kör du kommentaren till exempel:

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

Där secs_running är filtreringsstrategin så att endast operationer som har tagit mer än 5 sekunder att utföra kommer att returneras, vilket minskar utmatningen. Detta används ofta när CPU:ns hälsa kan bedömas till 100 % på grund av negativ prestandapåverkan som det kan påverka databasen. Så genom att ändra värdena kommer du att lära dig vilka frågor som tar lång tid att köra.

De returnerade dokumenten har följande som nycklar av intresse:

  • fråga :vad frågan innebär
  • aktiv : om frågan fortfarande pågår.
  • ns :samlingsnamn som frågan ska köras mot
  • secs_running :  hur lång tid frågan har tagit hittills i sekunder

Genom att markera vilka frågor som tar lång tid har du identifierat vad som överbelastas processorn.

Tolka resultat och åtgärda problemen

 Som vi har beskrivit ovan är frågefördröjningen mycket beroende av mängden data som är involverad, vilket annars kommer att leda till ineffektiva exekveringsplaner. Det vill säga, om du till exempel inte använder index i din samling och vill uppdatera vissa poster, måste operationen gå igenom alla dokument istället för att filtrera efter endast de som matchar frågespecifikationen. Logiskt sett kommer detta att ta längre tid, vilket leder till en långsam fråga. Du kan undersöka en ineffektiv exekveringsplan genom att köra:  explain(‘executionStats’) som ger statistik om frågans prestanda. Från denna punkt kan du lära dig hur frågan använder indexet förutom att ge en ledtråd om indexet är optimalt.

Om förklara-hjälpen returnerar

{

   "queryPlanner" : {

         "plannerVersion" : 1,

         ...

         "winningPlan" : {

            "stage" : "COLLSCAN",

            ...

         }

   },

   "executionStats" : {

      "executionSuccess" : true,

      "nReturned" : 3,

      "executionTimeMillis" : 0,

      "totalKeysExamined" : 0,

      "totalDocsExamined" : 10,

      "executionStages" : {

         "stage" : "COLLSCAN",

         ...

      },

      ...

   },

   ...

}

queryPlanner.winningPlan.stage:COLLSCAN-nyckelvärdet indikerar att mongoden var tvungen att skanna hela insamlingsdokumentet för att identifiera resultaten, så det blir en dyr operation som leder till långsamma frågor.

executionStats.totalKeysExamined:0 betyder att samlingen inte använder indexeringsstrategi

För en given fråga bör antalet inblandade dokument vara nära noll. Om antalet dokument är ganska stort finns det två möjligheter:

  1. Använder inte indexering med samlingen
  2. Använda ett index som inte är optimalt.

För att skapa ett index för en samling kör kommandot: 

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

Där kvantitet är ett exempelfält som du har valt för att vara optimalt för indexeringsstrategin.

Om du vill lära dig mer om indexering och vilken indexeringsstrategi du ska använda, kolla in den här bloggen

Slutsats

Försämring av databasprestanda kan lätt skildras genom att ha långsamma frågor, vilket är den minsta förväntan vi skulle vilja att plattformsanvändare ska stöta på. Man kan identifiera långsamma frågor i MongoDB genom att aktivera profileraren och konfigurera den till dess vissa specifikationer eller exekvera db.currentOp() på en körande mongod-instans.

Genom att titta på tidsparametrarna på det returnerade resultatet kan vi identifiera vilka frågor som släpar efter. Efter att ha identifierat dessa frågor använder vi förklara-hjälpen för dessa frågor för att få mer information, till exempel om frågan använder något index.

Utan indexering blir operationerna dyra eftersom många dokument måste skannas igenom innan ändringarna tillämpas. Med detta bakslag kommer CPU:n att bli överarbetad, vilket resulterar i långsamma frågeställningar och stigande CPU-spik.

Det största misstaget som leder till långsamma frågor är ineffektiv exekveringsplanering som enkelt kan lösas genom att använda ett index med den inblandade samlingen.


  1. Ansluter du till mongodb via webbläsaren?

  2. MongoDb-anslutning nekades

  3. Vad är Hadoop Mapper Class i MapReduce?

  4. Låsning och Redis