Kolejny tydzień z Uniwersystetu MongoDB przebiegł pod znakiem wydajności. A jak wydajność bazy danych to oczywiście indeksy. I właśnie o tych indeksach chłonąłem wiedzę przez cały tydzień.
Aby utworzyć indeks należy wywołać polecenie podobne do poniższego
db.students.createIndex({student_id:1})
gdzie znaczy 1-ascending, a -1 descending, ma to znaczenie wykorzystywaniu indeksów.
Aby usunąć indeks wystarczy wywołać linijkę podobną do:
db.students.dropIndex({name_of_the_index})
a jeżeli zapomnieliśmy nazwę indeksu to można sobie ją przypomnieć:
db.students.getIndexes()
Ale co jeżeli chcemy utworzyć indeks na kilku polach. Nic prostszego:
db.students.createIndex({student_id:1, class_id:-1})
możemy nawet włączyć do indeksu element tablicy:
db.students.createIndex({'scores.score':1})
ALE TYLKO JEDEN! Jeżeli będziemy próbować utworzyć indeks na dwóch elementach tablicy, albo wstawić do kolekcji dokument, który będzie zawierać tablice w więcej niż jednym indeksowanym polu to dostaniemy błąd, że się nie da.
Możemy też chcieć utworzyć unikalny indeks, i tu z pomocą przychodzi nam:
db.students.createIndex({student_id:1}, {unique: true})
Taki indeks zapewni nam wystąpienie unikalnych wartości w polu student_id.
Jeżeli podczas zakładania tego indeksu okaże się, że więcej niż jeden dokument zawiera tą samą wartość to polecenie:
db.students.remove({student_id:5}, {justOne: true})
usunie nam duble, ale lepiej z tym uważać.
Może się jednak zdarzyć, że będziemy chcieli utworzyć unikalny indeks na polu, które nie występuje w każdym dokumencie. Nie da się tego zrobić w standardowy (powyższy) sposób ze względu na nulle w kilku dokumentach. Z pomocą przychodzi sparse indeks:
db.students.createIndex({cellPhone:1}, {unique: true, sparse: true})
który nam taki indeks utworzy, ale należy pamiętać, że w takim indeksie nie pojawią się dokumenty, które nie zawierają cellPhone.
No dobrze, ale kiedy utworzyć indeks? Z pomocą przychodzi nam polecenie:
db.students.explain().find({student_id:5})
które zanalizuje nam zapytanie pod kątem ilości skanów dokumentów i indeksów. Standardowo explain jest wywoływany w trybie queryPlanner. Jeżeli chcemy uzyskać więcej informacji na temat planu wykonania zapytania to możemy skorzystać z opcji executionStats lub allPlansExecution:
db.students.explain("executionStats").find({students_id: 10}) db.students.explain("allPlansExecution").find({students_id: 10})
Kolejna część kursu daje nam wiedzę na temat sposobu tworzenia indeksów. Pamiętajmy, że możemy mieć miliony dokumentów w środowisku produkcyjnym i tworzenie indeksów musi być decyzją przemyślaną zarówno pod każdym względem.
W MongoDB indeksy tworzone są w dwóch trybach:
- foreground – szybki, ale blokuje zapisy i odczyty(domyślny)
- background – wolny, ale nie blokuje kolekcji.
db.students.createIndex({student_id:1}, {background: true})
Tworząc złożone indeksy należy pamiętać o następujących priorytetach operacji do jakich zwykle będzie używany indeks. Najpierw indeksujemy kolumny, do których będzie używane Equality, potem Sort, a na końcu Range. Zapewni nam to wydajne korzystanie z indeksów.
Kurs porusza również pojęcie „covered queries”, czyli takich, których wykonanie bazuje tylko i wyłącznie na skanowaniu indeksu bez potrzeby skanowania kolekcji.
Tworząc złożone indeksy należy pamiętać o następujących priorytetach operacji do jakich zwykle będzie on używany. Najpierw indeksujemy kolumny, do których będzie używane Equality, potem Sort, a na końcu Range.
Profilowanie zapytań do bazy może być zdefiniowane podczas uruchomienia MongoDB
mongod --dbpath c:\Projects\MongoDB\Data --profile 1 --slowms 5
- 0 – wyłączony
- 1 – wolne zapytania (domyślnie dłuższe niż 100ms)
- 2 – wszystkie zapytania
jeżeli chcemy zmienić parametr długości zapytania, które ma być logowane, możemy to zrobić poprzez ustawienie flagi –slowms (jak w powyższym przykładzie).
Na koniec zostają omówione dwa polecenia: mongotop i mongostat.
Praca domowa to cztery zadania związane z budową i analizą zapytań pod kątem wykorzystania indeksów.