sql >> Databasteknik >  >> NoSQL >> MongoDB

Hur fungerar sortering med ett index i MongoDB?

Index i MongoDB lagras i en B-trädstruktur, där varje indexpost pekar på en specifik plats på disken. Att använda en B-trädstruktur innebär också att ett MongoDB-index lagras i sorterad ordning, alltid passerat i ordning, och är billigt för MongoDB att hämta en serie dokument i sorterad ordning via index.

Uppdatera :B-trädstrukturen är sant för MMAPv1-lagringsmotorn, men implementeras något annorlunda av WiredTiger-lagringsmotorn (standard sedan MongoDB 3.2). Grundidén förblir densamma, där det är billigt att gå igenom indexet i en sorterad ordning.

En SORT steg (dvs. sortering i minnet) i en fråga är begränsad till 32 MB minnesanvändning. En fråga misslyckas om SORT steget överskrider denna gräns. Denna gräns kan kringgås genom att använda den sorterade naturen hos index, så att MongoDB kan returnera en fråga med en sort() parameter utan att utföra en sortering i minnet.

Låt oss anta att frågan har formen:

    db.a.find({b:{$gt:100}, c:{$gt:200}}).sort(...)

med samling a har ett index på:

    db.a.createIndex({b:1,c:1})

Det finns två möjliga scenarier när en sort() steg anges i frågan:

1. MongoDB kan inte använda indexets sorterade karaktär och måste utföra en SORT i minnet scen .

Detta är resultatet om frågan inte kan använda "indexprefixet". Till exempel:

    db.a.find({b:{$gt:100}, c:{$gt:200}}).sort({c:1})

I frågan ovan, indexet {b:1,c:1} kan användas för att:

  • Matcha dokument med b större än 100 för {b:{$gt:100}} del av frågan.
  • Men det finns ingen garanti för att de returnerade dokumenten sorteras i termer av c .

Därför har MongoDB inget annat val än att utföra en sortering i minnet. explain() utdata från denna fråga kommer att ha en SORT skede. Denna SORT scenen skulle begränsas till 32 MB minnesanvändning.

2. MongoDB kan använda indexets sorterade natur .

Detta är resultatet om frågan använder:

  • Sorteringsnycklar som matchar indexets ordning, och
  • Anger samma ordning som indexet (dvs. indexet {b:1,c:1} kan användas för sort({b:1,c:1}) eller sort({b:-1,c:-1}) men inte sort({b:1,c:-1}) )

Till exempel:

    db.a.find({b:{$gt:100}, c:{$gt:200}}).sort({b:1})

I frågan ovan, indexet {b:1,c:1} kan användas för att:

  • Matcha dokument med b större än 100 för {b:{$gt:100}} del av frågan.
  • I det här fallet kan MongoDB garantera att de returnerade dokumenten sorteras i termer av b .

explain() utdata från frågan ovan inte har en SORT skede. Dessutom explain() utdata från frågan med och utan sort() är identiska . I huvudsak får vi sort() gratis.

En värdefull resurs för att förstå detta ämne är Optimering av MongoDB Compound Indexes. Observera att det här blogginlägget skrevs långt tillbaka 2012. Även om en del av terminologin kan vara föråldrad är det tekniska i inlägget fortfarande relevant.

Uppdatering om uppföljningsfrågor

  1. MongoDB använder bara ett index för de flesta frågor. Så till exempel för att undvika en SORT i minnet steg i frågan

    db.a.find({a:1}).sort({b:1})
    

    indexet måste täcka både a och b fält samtidigt; t.ex. ett sammansatt index som {a:1,b:1} krävs. Du kan inte ha två separata index {a:1} och {b:1} , och förvänta dig {a:1} index som ska användas för likhetsdelen och {b:1} index som ska användas för sorteringsdelen. I det här fallet kommer MongoDB att välja ett av de två indexen.

    Därför är det korrekt att resultaten sorteras eftersom de slås upp och returneras i indexordningen.

  2. För att undvika en sortering i minnet med ett sammansatt index måste första delen av indexet tillgodose jämställdhetsdelen av frågan, och den andra delen måste tillgodose sorteringsdelen av frågan (som visas i förklaringen till (1) ovan).

    Om du har en fråga som denna:

    db.a.find({}).sort({a:1})
    

    indexet {a:1,b:1} kan användas för sorteringsdelen (eftersom du i princip returnerar hela samlingen). Och om din fråga ser ut så här:

    db.a.find({a:1}).sort({b:1})
    

    samma index {a:1,b:1} kan också användas för båda delarna av frågan. Även:

    db.a.find({a:1,b:1})
    

    kan också använda samma index {a:1,b:1}

    Lägg märke till mönstret här:find() följt av sort() parametrarna följer indexordningen {a:1,b:1} . Därför måste ett sammansatt index sorteras efter likhet -> sortering .

Uppdatering angående sortering av olika typer

Om ett fält har olika typer mellan dokument (t.ex. om a är sträng i ett dokument, nummer i andra, booleskt i ytterligare ett annat), hur går sorteringen till?

Svaret är MongoDB BSON-typ jämförelseorder. För att parafrasera manualsidan är ordningen:

  1. MinKey (intern typ)
  2. Null
  3. Siffror (ints, longs, doubles, decimals)
  4. Symbol, sträng
  5. Objekt
  6. Array
  7. BinData
  8. ObjectId
  9. Boolesk
  10. Datum
  11. Tidsstämpel
  12. Reguljärt uttryck
  13. MaxKey (intern typ)

Så från exemplet ovan med stigande ordning visas dokument som innehåller siffror först, sedan strängar och sedan booleska.




  1. Skanna strängar med nodejs i redis

  2. Kan Redis 6 dra fördel av flerkärniga processorer?

  3. MongoDB utskriftsavstånd mellan två punkter

  4. MongoDB 'count()' är väldigt långsam. Hur förfinar/arbetar vi med det?