To dużo pytań w jednym poście;) Pozwólcie, że przejdę je w praktycznej kolejności :
- Każde zapytanie może używać co najwyżej jednego indeksu (z wyjątkiem klauzul najwyższego poziomu $lub itp.). Obejmuje to wszelkie sortowanie.
- Ze względu na powyższe na pewno będziesz potrzebować indeksu złożonego dla swojego problemu, a nie oddzielnych indeksów dla poszczególnych pól.
- Pola o niskiej kardynalności (czyli pola z bardzo małą liczbą unikalnych wartości w Twoim zbiorze danych) zwykle nie powinny znajdować się w indeksie, ponieważ ich selektywność jest bardzo ograniczona.
- Kolejność pól w indeksie złożonym ma znaczenie, podobnie jak względny kierunek każdego pola w indeksie złożonym (np. „{imię:1, wiek:-1}”). Istnieje wiele dokumentacji na temat indeksów złożonych i kierunków pól indeksowych na mongodb.org, więc nie będę tego tutaj powtarzał.
- Sortowanie będzie używać indeksu tylko wtedy, gdy pole sortowania znajduje się w indeksie i jest polem w indeksie bezpośrednio po ostatnim polu użytym do wybrania zestawu wyników. W większości przypadków byłoby to ostatnie pole indeksu.
Tak więc nie należy w ogóle uwzględniać stanu w indeksie, ponieważ gdy spacer po indeksie wyeliminuje zdecydowaną większość dokumentów opartych na polach o wyższej liczności, w większości przypadków pozostaną co najwyżej 2-3 dokumenty, co nie jest zoptymalizowane przez indeks stanu (zwłaszcza, że wspomniałeś, że te 2-3 dokumenty i tak mają ten sam status).
Teraz ostatnia uwaga, która jest istotna w twoim przypadku, to to, że gdy używasz zapytań o zakres (i tak jest), indeks i tak nie będzie używał do sortowania. Możesz to sprawdzić, patrząc na wartość „scanAndOrder” funkcji explain() po przetestowaniu zapytania. Jeśli ta wartość istnieje i jest prawdziwa, oznacza to, że zestaw wyników zostanie posortowany w pamięci (skanuj i uporządkuj), a nie bezpośrednio użyje indeksu. Nie można tego uniknąć w Twoim konkretnym przypadku.
Dlatego indeks powinien wyglądać następująco:
db.posts.ensureIndex({start:1, end:1})
i twoje zapytanie (kolejność zmodyfikowana tylko dla jasności, optymalizator zapytań uruchomi twoje oryginalne zapytanie przez tę samą ścieżkę wykonania, ale wolę umieszczać indeksowane pola na początku i w kolejności):
db.posts.find({start: {$lt: today}, end: {$gt: today}, status: {$gte:0}}).sort({sortOrder:1})