sql >> Databasteknik >  >> NoSQL >> MongoDB

MongoDB frågar prestanda för över 5 miljoner poster

Detta är att söka efter nålen i en höstack. Vi skulle behöva lite utdata av explain() för de frågor som inte fungerar bra. Tyvärr skulle även det lösa problemet bara för den specifika frågan, så här är en strategi för hur man kan närma sig detta:

  1. Se till att det inte beror på otillräckligt RAM-minne och överdriven personsökning
  2. Aktivera DB-profileraren (med db.setProfilingLevel(1, timeout) där timeout är tröskeln för antalet millisekunder som frågan eller kommandot tar, kommer allt långsammare att loggas)
  3. Inspektera de långsamma frågorna i db.system.profile och kör frågorna manuellt med explain()
  4. Försök att identifiera de långsamma operationerna i explain() utdata, såsom scanAndOrder eller stor nskannad osv.
  5. Anledning till frågans selektivitet och om det är möjligt att förbättra frågan med hjälp av ett index överhuvudtaget . Om inte, överväg att inte tillåta filterinställningen för slutanvändaren eller ge honom en varningsdialogruta om att operationen kan vara långsam.

Ett nyckelproblem är att du tydligen tillåter dina användare att kombinera filter efter behag. Utan indexkorsning kommer det att spränga antalet nödvändiga index dramatiskt.

Att blint kasta ett index vid varje möjlig fråga är också en mycket dålig strategi. Det är viktigt att strukturera frågorna och se till att de indexerade fälten har tillräcklig selektivitet .

Låt oss säga att du har en fråga för alla användare med status "aktiv" och några andra kriterier. Men av de 5 miljoner användarna är 3 miljoner aktiva och 2 miljoner inte, så över 5 miljoner inlägg finns det bara två olika värden. Ett sådant index brukar inte hjälpa. Det är bättre att först söka efter de andra kriterierna och sedan skanna resultaten. I genomsnitt, när du returnerar 100 dokument, måste du skanna 167 dokument, vilket inte skadar prestandan så mycket. Men det är inte så enkelt. Om det primära kriteriet är joined_at användarens datum och sannolikheten för att användare slutar använda med tiden är hög, kan det sluta med att du måste skanna tusentals av dokument innan man hittar hundra matchningar.

Så optimeringen beror väldigt mycket på data (inte bara dess struktur , men också data själv ), dess interna korrelationer och dina frågemönster .

Saker och ting blir värre när datan är för stor för RAM-minnet, för då är det bra att ha ett index, men att skanna (eller till och med bara returnera) resultaten kan kräva att man hämtar mycket data från disken slumpmässigt, vilket tar mycket tid.

Det bästa sättet att kontrollera detta är att begränsa antalet olika frågetyper, inte tillåta frågor på information med låg selektivitet och försöka förhindra slumpmässig åtkomst till gamla data.

Om allt annat misslyckas och om du verkligen behöver så mycket flexibilitet i filter, kan det vara värt att överväga en separat sök-DB som stöder indexkorsningar, hämta mongo-id:n därifrån och sedan hämta resultaten från mongo med $in . Men det är fyllt med sina egna faror.

-- REDIGERA --

Förklaringen du postade är ett vackert exempel på problemet med att skanna fält med låg selektivitet. Tydligen finns det många dokument för "[email protected]". Nu går det ganska snabbt att hitta dessa dokument och sortera dem fallande efter tidsstämpel, eftersom det stöds av index med hög selektivitet. Tyvärr, eftersom det bara finns två enhetstyper, måste mongo skanna 30060 dokument för att hitta den första som matchar "mobil".

Jag antar att detta är någon form av webbspårning, och användarens användningsmönster gör frågan långsam (skulle han byta mobil och webb dagligen skulle frågan vara snabb).

Att göra just denna fråga snabbare skulle kunna göras med hjälp av ett sammansatt index som innehåller enhetstypen, t.ex. använder

a) ensureIndex({'username': 1, 'userAgent.deviceType' : 1, 'timestamp' :-1})

eller

b) ensureIndex({'userAgent.deviceType' : 1, 'username' : 1, 'timestamp' :-1})

Tyvärr betyder det att frågor som find({"username" :"foo"}).sort({"timestamp" :-1}); kan inte använda samma index längre, så, som beskrivits, kommer antalet index att växa mycket snabbt.

Jag är rädd att det inte finns någon bra lösning för detta med mongodb för närvarande.



  1. Söksträng med specialtecken i MongoDB-dokument

  2. Hur lagrar man ett binärt objekt i redis med hjälp av nod?

  3. Cachar JSON-objekt på serversidan

  4. Catbox-redis visar frånkopplat fel på min hapijs-applikation