Det er mange spørgsmål i et indlæg;) Lad mig gennemgå dem i en praktisk rækkefølge :
- Hver forespørgsel kan højst bruge ét indeks (med undtagelse af $eller klausuler på øverste niveau og sådan). Dette inkluderer enhver sortering.
- På grund af ovenstående vil du helt sikkert have brug for et sammensat indeks for dit problem frem for separate indekser pr. felt.
- Felter med lav kardinalitet (altså felter med meget få unikke værdier på tværs af dit datasæt) bør normalt ikke være i indekset, da deres selektivitet er meget begrænset.
- Rækkefølgen af felterne i dit sammensatte indeks har betydning, og det samme gør den relative retning af hvert felt i dit sammensatte indeks (f.eks. "{navn:1, alder:-1}"). Der er meget dokumentation om sammensatte indekser og indeksfeltvejledninger på mongodb.org, så jeg vil ikke gentage det hele her.
- Sortering vil kun bruge indekset, hvis sorteringsfeltet er i indekset og er feltet i indekset direkte efter det sidste felt, der blev brugt til at vælge resultatsættet. I de fleste tilfælde vil dette være det sidste felt i indekset.
Så du bør slet ikke inkludere status i dit indeks, da når først indeksvandringen har elimineret langt de fleste dokumenter baseret på felter med højere kardinalitet, vil den højst have 2-3 dokumenter tilbage i de fleste tilfælde, hvilket næppe er optimeret af et statusindeks (især da du nævnte, at de 2-3 dokumenter med stor sandsynlighed alligevel har samme status).
Den sidste bemærkning, der er relevant i dit tilfælde, er, at når du bruger intervalforespørgsler (og det gør du), vil den alligevel ikke bruge indekset til sortering. Du kan tjekke dette ved at se på "scanAndOrder"-værdien af din explain(), når du har testet din forespørgsel. Hvis denne værdi eksisterer og er sand, betyder det, at den vil sortere resultatsættet i hukommelsen (scan og orden) i stedet for at bruge indekset direkte. Dette kan ikke undgås i dit specifikke tilfælde.
Så dit indeks bør derfor være :
db.posts.ensureIndex({start:1, end:1})
og din forespørgsel (rækkefølgen er kun ændret for klarhedens skyld, forespørgselsoptimering vil køre din oprindelige forespørgsel gennem den samme udførelsessti, men jeg foretrækker at sætte indekserede felter først og i rækkefølge) :
db.posts.find({start: {$lt: today}, end: {$gt: today}, status: {$gte:0}}).sort({sortOrder:1})