MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Jak działa sortowanie z indeksem w MongoDB?

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 do sort({b:1,c:1}) lub sort({b:-1,c:-1}) ale nie sort({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

  1. MongoDB używa tylko jednego indeksu dla większości zapytań. Na przykład, aby uniknąć w pamięci SORT etap w zapytaniu

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

    indeks musi obejmować zarówno a i b 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.

  2. 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ępuje sort() 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:

  1. MinKey (typ wewnętrzny)
  2. Numer
  3. Liczby (int, long, double, dziesiętne)
  4. Symbol, ciąg
  5. Obiekt
  6. Tablica
  7. BinData
  8. Identyfikator obiektu
  9. Boole'a
  10. Data
  11. sygnatura czasowa
  12. Wyrażenie regularne
  13. 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.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jak znaleźć podciąg w polu w Mongodb

  2. Zmiana katalogu magazynu danych MongoDB

  3. Określanie najlepszej architektury do wdrożenia klastra MongoDB

  4. $unset na wielu polach w mongodb

  5. Nie można połączyć się z serwerem 127.0.0.1:27017