Indeksy w MongoDB są przechowywane w strukturze B-drzewa, gdzie każdy wpis indeksu wskazuje określoną lokalizację na dysku. Korzystanie ze struktury B-drzewa oznacza również, że indeks MongoDB jest przechowywany w posortowanej kolejności, zawsze przeszukiwany w kolejności, a pobieranie przez MongoDB serii dokumentów w posortowanej kolejności za pomocą indeksów jest tanie.
Aktualizacja :Struktura B-drzewa jest prawdziwa dla silnika pamięci masowej MMAPv1, ale jest zaimplementowana nieco inaczej przez silnik pamięci masowej WiredTiger (domyślnie od MongoDB 3.2). Podstawowa idea pozostaje taka sama, ponieważ przechodzenie po indeksie w posortowanej kolejności jest tanie.
SORT
etap (tj. sortowanie w pamięci) w zapytaniu jest ograniczone do 32 MB wykorzystania pamięci. Zapytanie zakończy się niepowodzeniem, jeśli SORT
etap przekracza ten limit. Ten limit można ominąć, wykorzystując posortowaną naturę indeksów, dzięki czemu MongoDB może zwrócić zapytanie z sort()
parametr bez wykonywania sortowania w pamięci.
Załóżmy, że zapytanie ma postać:
db.a.find({b:{$gt:100}, c:{$gt:200}}).sort(...)
z kolekcją a
o indeksie:
db.a.createIndex({b:1,c:1})
Istnieją dwa możliwe scenariusze, gdy sort()
etap jest określony w zapytaniu:
1. MongoDB nie może używać posortowanej natury indeksu i musi wykonać w pamięci SORT
scena .
Jest to wynik, jeśli zapytanie nie może użyć „prefiksu indeksu”. Na przykład:
db.a.find({b:{$gt:100}, c:{$gt:200}}).sort({c:1})
W powyższym zapytaniu indeks {b:1,c:1}
może być używany do:
- Dopasuj dokumenty mające
b
większe niż 100 dla{b:{$gt:100}}
część zapytania. - Jednak nie ma gwarancji, że zwracane dokumenty są sortowane według
c
.
Dlatego MongoDB nie ma innego wyjścia, jak wykonać sortowanie w pamięci. explain()
wyjście tego zapytania będzie miało SORT
scena. To SORT
scena będzie ograniczona do 32 MB wykorzystania pamięci.
2. MongoDB może używać posortowanej natury indeksu .
To jest wynik, jeśli zapytanie używa:
- Sortuj klucze pasujące do kolejności indeksu i
- Określa tę samą kolejność co indeks (tj. indeks
{b:1,c:1}
może być użyty dosort({b:1,c:1})
lubsort({b:-1,c:-1})
ale niesort({b:1,c:-1})
)
Na przykład:
db.a.find({b:{$gt:100}, c:{$gt:200}}).sort({b:1})
W powyższym zapytaniu indeks {b:1,c:1}
może być używany do:
- Dopasuj dokumenty mające
b
większe niż 100 dla{b:{$gt:100}}
część zapytania. - W tym przypadku MongoDB może zagwarantować, że zwracane dokumenty są sortowane według
b
.
explain()
wynik powyższego zapytania nie mieć SORT
scena. Ponadto explain()
wyjście zapytania z i bez sort()
są identyczne . Zasadniczo otrzymujemy sort()
za darmo.
Wartościowym źródłem do zrozumienia tego tematu jest Optymalizacja indeksów złożonych MongoDB. Pamiętaj, że ten post na blogu został napisany w 2012 roku. Chociaż niektóre terminy mogą być nieaktualne, techniczne posty są nadal aktualne.
Aktualizacja na pytania uzupełniające
-
MongoDB używa tylko jednego indeksu dla większości zapytań. Na przykład, aby uniknąć w pamięci
SORT
etap w zapytaniudb.a.find({a:1}).sort({b:1})
indeks musi obejmować zarówno
a
ib
pola w tym samym czasie; np. indeks złożony, taki jak{a:1,b:1}
jest wymagane. Nie możesz mieć dwóch oddzielnych indeksów{a:1}
i{b:1}
i oczekuj{a:1}
indeks używany dla części równości i{b:1}
indeks, który ma być używany dla części sortowania. W takim przypadku MongoDB wybierze jeden z dwóch indeksów.Dlatego prawidłowe jest sortowanie wyników, ponieważ są one wyszukiwane i zwracane w kolejności indeksu.
-
Aby uniknąć sortowania w pamięci przy użyciu indeksu złożonego, pierwsza część indeksu musi odpowiadać części równości zapytania, a druga część musi odpowiadać części sortowania zapytania (jak pokazano w wyjaśnieniu do punktu (1) powyżej).
Jeśli masz takie zapytanie:
db.a.find({}).sort({a:1})
indeks
{a:1,b:1}
może być użyty jako część sortowania (ponieważ w zasadzie zwracasz całą kolekcję). A jeśli Twoje zapytanie wygląda tak:db.a.find({a:1}).sort({b:1})
ten sam indeks
{a:1,b:1}
może być również użyty dla obu części zapytania. Również:db.a.find({a:1,b:1})
może również używać tego samego indeksu
{a:1,b:1}
Zwróć uwagę na wzorzec tutaj:
find()
po którym następujesort()
parametry są zgodne z kolejnością indeksowania{a:1,b:1}
. Dlatego indeks złożony musi być uporządkowany według równości -> sortowania .
Aktualizacja dotycząca sortowania różnych typów
Jeśli pole ma różne typy między dokumentami (np. jeśli a
to ciąg w jednym dokumencie, liczba w innych, wartość logiczna w jeszcze), jak przebiega sortowanie?
Odpowiedzią jest kolejność porównania typu MongoDB BSON. Parafrazując stronę podręcznika, kolejność jest następująca:
- MinKey (typ wewnętrzny)
- Numer
- Liczby (int, long, double, dziesiętne)
- Symbol, ciąg
- Obiekt
- Tablica
- BinData
- Identyfikator obiektu
- Boole'a
- Data
- sygnatura czasowa
- Wyrażenie regularne
- MaxKey (typ wewnętrzny)
Tak więc z powyższego przykładu używającego kolejności rosnącej, dokumenty zawierające liczby pojawią się jako pierwsze, następnie ciągi, a następnie wartości logiczne.