Du kan tänka på MongoDB enfältsindex som en array, med pekare till dokumentplatser. Till exempel, om du har en samling med (observera att sekvensen är avsiktligt ur funktion):
[collection]
1: {a:3, b:2}
2: {a:1, b:2}
3: {a:2, b:1}
4: {a:1, b:1}
5: {a:2, b:2}
Enkelfältsindex
Om du nu gör det:
db.collection.createIndex({a:1})
Indexet ser ungefär ut så här:
[index a:1]
1: {a:1} --> 2, 4
2: {a:2} --> 3, 5
3: {a:3} --> 1
Notera tre viktiga saker:
- Det är sorterat efter
a
stigande - Varje post pekar på platsen där de relevanta dokumenten finns
- Indexet registrerar bara värdena för
a
fält.b
fältet finns inte alls i indexet
Så om du gör en fråga som:
db.collection.find().sort({a:1})
Allt den behöver göra är att gå indexet uppifrån och ned, hämta och mata ut dokumentet som posterna pekar på. Observera att du också kan gå indexet från botten, t.ex.:
db.collection.find().sort({a:-1})
och den enda skillnaden är att du går indexet baklänges.
Eftersom b
inte finns i indexet alls, kan du inte använda indexet när du frågar något om b
.
Sammansatt index
I ett sammansatt index, t.ex.:
db.collection.createIndex({a:1, b:1})
Det betyder att du vill sortera efter a
först, sortera sedan efter b
. Indexet skulle se ut så här:
[index a:1, b:1]
1: {a:1, b:1} --> 4
2: {a:1, b:2} --> 2
3: {a:2, b:1} --> 3
4: {a:2, b:2} --> 5
5: {a:3, b:2} --> 1
Observera att:
- Indexet är sorterat från
a
- Inom varje
a
du har en sorteradb
- Du har 5 indexposter jämfört med bara tre i det föregående exemplet med ett fält
Med detta index kan du göra en fråga som:
db.collection.find({a:2}).sort({b:1})
Det kan lätt hitta var a:2
gå sedan indexet framåt. Med tanke på det indexet kan du inte göra :
db.collection.find().sort({b:1})
db.collection.find({b:1})
I båda frågorna kan du inte enkelt hitta b
eftersom den är spridd över hela indexet (dvs inte i sammanhängande poster). Hur du än kan gör:
db.collection.find({a:2}).sort({b:-1})
eftersom du i princip kan hitta var a:2
är och gå b
poster bakåt.
Redigera :förtydligande av @marcospgps fråga i kommentaren:
Möjligheten att använda indexet {a:1, b:1}
för att tillfredsställa find({a:2}).sort({b:-1})
faktiskt vettigt om du ser det från en sorterad tabellsynpunkt. Till exempel indexet {a:1, b:1}
kan ses som:
a | b
--|--
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2
find({a:2}).sort({b:1})
Indexet {a:1, b:1}
betyder sort by a, then within each a, sort the b values
. Om du sedan gör en find({a:2}).sort({b:1})
, indexet vet var alla a=2
är. Inom detta block av a=2
, b
skulle sorteras i stigande ordning (enligt indexspecifikationen), så att frågan find({a:2}).sort({b:1})
kan tillfredsställas av:
a | b
--|--
1 | 1
1 | 2
2 | 1 <-- walk this block forward to satisfy
2 | 2 <-- find({a:2}).sort({b:1})
2 | 3 <--
3 | 1
3 | 2
find({a:2}).sort({b:-1})
Eftersom indexet kan gå framåt eller bakåt, följdes en liknande procedur, med en liten vridning i slutet:
a | b
--|--
1 | 1
1 | 2
2 | 1 <-- walk this block backward to satisfy
2 | 2 <-- find({a:2}).sort({b:-1})
2 | 3 <--
3 | 1
3 | 2
Det faktum att indexet kan gå framåt eller bakåt är nyckeln som möjliggör frågan find({a:2}).sort({b:-1})
för att kunna använda indexet {a:1, b:1}
.
Frågeplaneraren förklarar
Du kan se vad frågeplaneraren planerar genom att använda db.collection.explain().find(....)
. I grund och botten om du ser en stage
av COLLSCAN
, inget index användes eller kan användas för frågan. Se förklara resultat
för detaljer om kommandots utdata.