sql >> Database teknologi >  >> NoSQL >> MongoDB

Hvordan fungerer sortering med et indeks i MongoDB?

Indekser i MongoDB er gemt i en B-træstruktur, hvor hver indeksindgang peger på en bestemt placering på disken. Brug af en B-træstruktur betyder også, at et MongoDB indeks lagres i en sorteret rækkefølge, altid krydses i rækkefølge, og det er billigt for MongoDB at hente en række dokumenter i en sorteret rækkefølge via indekser.

Opdater :B-træstrukturen er sand for MMAPv1-lagringsmotoren, men implementeres lidt anderledes af WiredTiger-lagringsmotoren (standard siden MongoDB 3.2). Grundideen forbliver den samme, hvor det er billigt at krydse indekset i en sorteret rækkefølge.

En SORT fase (dvs. sortering i hukommelsen) i en forespørgsel er begrænset til 32 MB hukommelsesbrug. En forespørgsel vil mislykkes, hvis SORT fase overskrider denne grænse. Denne grænse kan omgås ved at bruge den sorterede karakter af indekser, så MongoDB kan returnere en forespørgsel med en sort() parameter uden at udføre en sortering i hukommelsen.

Lad os antage, at forespørgslen har formen:

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

med samling a have et indeks på:

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

Der er to mulige scenarier, når en sort() fase er angivet i forespørgslen:

1. MongoDB kan ikke bruge indeksets sorterede karakter og skal udføre en SORT i hukommelsen scene .

Dette er resultatet, hvis forespørgslen ikke kan bruge "indekspræfikset". For eksempel:

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

I forespørgslen ovenfor, indekset {b:1,c:1} kan bruges til at:

  • Match dokumenter med b større end 100 for {b:{$gt:100}} del af forespørgslen.
  • Der er dog ingen garanti for, at de returnerede dokumenter er sorteret efter c .

Derfor har MongoDB intet andet valg end at udføre en sortering i hukommelsen. explain() output af denne forespørgsel vil have en SORT scene. Denne SORT fase ville være begrænset til 32 MB hukommelsesbrug.

2. MongoDB kan bruge indeksets sorterede natur .

Dette er resultatet, hvis forespørgslen bruger:

  • Sorteringsnøgler, der matcher rækkefølgen af ​​indekset, og
  • Specificerer den samme rækkefølge som indekset (dvs. indekset {b:1,c:1} kan bruges til sort({b:1,c:1}) eller sort({b:-1,c:-1}) men ikke sort({b:1,c:-1}) )

For eksempel:

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

I forespørgslen ovenfor, indekset {b:1,c:1} kan bruges til at:

  • Match dokumenter med b større end 100 for {b:{$gt:100}} del af forespørgslen.
  • I dette tilfælde kan MongoDB garantere, at de returnerede dokumenter er sorteret efter b .

explain() output fra forespørgslen ovenfor vil ikke har en SORT scene. Også explain() output af forespørgslen med og uden sort() er identiske . I bund og grund får vi sort() gratis.

En værdifuld ressource til at forstå dette emne er Optimering af MongoDB Compound Indexes. Bemærk venligst, at dette blogindlæg blev skrevet helt tilbage i 2012. Selvom noget af terminologien kan være forældet, er det tekniske ved indlægget stadig relevant.

Opdatering om opfølgende spørgsmål

  1. MongoDB bruger kun ét indeks til de fleste forespørgsler. Så for eksempel for at undgå en SORT i hukommelsen trin i forespørgslen

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

    indekset skal dække både a og b felter på samme tid; for eksempel. et sammensat indeks såsom {a:1,b:1} er påkrævet. Du kan ikke have to separate indekser {a:1} og {b:1} , og forvent {a:1} indeks, der skal bruges til lighedsdelen, og {b:1} indeks, der skal bruges til sorteringsdelen. I dette tilfælde vil MongoDB vælge et af de to indekser.

    Derfor er det korrekt, at resultaterne sorteres, fordi de slås op og returneres i rækkefølgen af ​​indekset.

  2. For at undgå at have en sortering i hukommelsen ved hjælp af et sammensat indeks, skal første del af indekset tage højde for ligestillingsdelen af forespørgslen, og anden del skal passe til sorteringsdelen af forespørgslen (som vist i forklaringen til (1) ovenfor).

    Hvis du har en forespørgsel som denne:

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

    indekset {a:1,b:1} kan bruges til sorteringsdelen (da du som udgangspunkt returnerer hele samlingen). Og hvis din forespørgsel ser sådan ud:

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

    det samme indeks {a:1,b:1} kan også bruges til begge dele af forespørgslen. Også:

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

    kan også bruge det samme indeks {a:1,b:1}

    Læg mærke til mønsteret her:find() efterfulgt af sort() parametre følger indeksrækkefølgen {a:1,b:1} . Derfor skal et sammensat indeks sorteres efter lighed -> sortering .

Opdatering vedrørende sortering af forskellige typer

Hvis et felt har forskellige typer mellem dokumenter (f.eks. hvis a er streng i ét dokument, nummer i andre, boolesk i endnu et andet), hvordan forløber sorteringen?

Svaret er MongoDB BSON-type sammenligningsrækkefølge. For at omskrive manualsiden er rækkefølgen:

  1. MinKey (intern type)
  2. Nul
  3. Tal (ints, longs, doubler, decimaler)
  4. Symbol, streng
  5. Objekt
  6. Array
  7. BinData
  8. ObjectId
  9. Boolesk
  10. Dato
  11. Tidsstempel
  12. Regulært udtryk
  13. MaxKey (intern type)

Så fra eksemplet ovenfor ved brug af stigende rækkefølge, vises dokumenter, der indeholder tal først, derefter strenge og derefter boolean.




  1. MongoDB-opslag, når fremmedfelt er en række objekter

  2. Én publikation skjuler indlejrede felter fra en anden publikation

  3. Kan jeg serialisere et ruby ​​Digest::SHA1-forekomstobjekt?

  4. Hvordan forespørger jeg efter forskellige værdier i Mongoose?