Indeksy w MySQL to bardzo złożona bestia. W przeszłości omawialiśmy indeksy MySQL, ale nigdy nie zagłębiliśmy się w nie głębiej — zrobimy to w tej serii wpisów na blogu. Ten wpis na blogu powinien służyć jako bardzo ogólny przewodnik po indeksach, podczas gdy inne części tej serii zagłębią się nieco głębiej w te tematy.
Co to są indeksy?
Ogólnie rzecz biorąc, jak już wspomniano w poprzednim poście na blogu dotyczącym indeksów, indeks jest alfabetyczną listą rekordów z odniesieniami do stron, na których są wymienione. W MySQL indeks to struktura danych używana najczęściej do szybkiego znajdowania wierszy. Możesz również usłyszeć termin „klucze” – odnosi się on również do indeksów.
Co robią indeksy?
W MySQL indeksy są używane do szybkiego znajdowania wierszy z określonymi wartościami kolumn i zapobiegania czytaniu całej tabeli w celu znalezienia wierszy istotnych dla zapytania. Indeksy są najczęściej używane, gdy dane przechowywane w systemie baz danych (na przykład MySQL) stają się większe, ponieważ im większa tabela, tym większe prawdopodobieństwo, że możesz skorzystać z indeksów.
Typy indeksów MySQL
Jeśli chodzi o MySQL, mogłeś słyszeć o tym, że ma wiele typów indeksów:
-
INDEX B-Tree - taki indeks jest często używany do przyspieszenia zapytań SELECT pasujących do klauzuli WHERE. Taki indeks może być używany w polach, w których wartości nie muszą być unikalne, akceptuje również wartości NULL.
-
INDEKS PEŁNOTEKSTOWY - taki indeks służy do korzystania z możliwości wyszukiwania pełnotekstowego. Ten typ indeksu znajduje słowa kluczowe w tekście zamiast bezpośrednio porównywać wartości z wartościami w indeksie.
-
UNIKALNY INDEKS jest często używany do usuwania zduplikowanych wartości z tabeli. Wymusza niepowtarzalność wartości wierszy.
-
KLUCZ PODSTAWOWY jest również indeksem - jest często używany razem z polami posiadającymi atrybut AUTO_INCREMENT. Ten typ indeksu nie akceptuje wartości NULL i raz ustawiony, wartości w kolumnie, która ma KLUCZ PODSTAWOWY, nie mogą zostać zmienione.
-
INDEKS ZJAZDOWY to indeks przechowujący wiersze w porządku malejącym. Ten typ indeksu został wprowadzony w MySQL 8.0 — MySQL będzie używał tego typu indeksu, gdy zapytanie jest żądane w kolejności malejącej.
Wybieranie optymalnych typów danych dla indeksów w MySQL
Jeśli chodzi o indeksy, należy również pamiętać, że MySQL obsługuje szeroką gamę typów danych, a niektóre typy danych nie mogą być używane razem z pewnymi rodzajami indeksów (na przykład FULLTEXT indeksy mogą być używane tylko na kolumnach tekstowych (CHAR, VARCHAR lub TEXT) - nie można ich używać na żadnych innych typach danych), więc przed faktycznym wyborem indeksów do projektu bazy danych, zdecyduj, jaki typ danych zamierzasz użyć w danej kolumnie (zdecyduj, jaką klasę danych zamierzasz przechowywać:czy chcesz przechowywać liczby? Wartości łańcuchowe? Zarówno liczby, jak i wartości łańcuchowe? itd.), a następnie zdecyduj, jaki zakres wartości zamierzasz przechowywać (wybierz ten, którego nie przekroczysz, ponieważ zwiększenie zakresu typów danych może być później czasochłonnym zadaniem - zalecamy użycie prostego typu danych), a jeśli nie zamierzasz używać NULL wartości w swoich kolumnach, określ swoje pola jako NOT NULL, kiedy tylko możesz - kiedy co dopuszczający wartość null lumn jest indeksowany, wymaga dodatkowego bajtu na wpis.
Wybieranie optymalnych zestawów znaków i sortowania dla indeksów w MySQL
Oprócz typów danych należy również pamiętać, że każdy znak w MySQL zajmuje miejsce. Na przykład znaki UTF-8 mogą zajmować od 1 do 4 bajtów każdy, więc możesz chcieć uniknąć indeksowania, na przykład 255 znaków i użyć tylko, powiedzmy, 50 lub 100 znaków dla określonej kolumny.
Korzyści i wady używania indeksów w MySQL
Główną korzyścią z używania indeksów w MySQL jest zwiększona wydajność zapytań wyszukiwania pasujących do klauzuli WHERE - indeksy przyspieszają zapytania SELECT pasujące do klauzuli WHERE, ponieważ MySQL nie czyta całej tabeli w celu znalezienia wierszy istotne dla zapytania. Pamiętaj jednak, że indeksy mają swoje wady. Najważniejsze z nich to:
-
Indeksy zajmują miejsce na dysku.
-
Indeksy obniżają wydajność zapytań INSERT, UPDATE i DELETE - gdy dane są aktualizowane, indeks musi być aktualizowane razem z nim.
-
MySQL nie chroni przed używaniem wielu typów indeksów jednocześnie. Innymi słowy, możesz użyć PRIMARY KEY, INDEX i UNIQUE INDEX w tej samej kolumnie - MySQL nie chroni Cię przed popełnieniem takiego błędu.
Jeśli podejrzewasz, że niektóre zapytania stają się wolniejsze, rozważ zajrzenie do zakładki Monitor zapytań w ClusterControl - włączając monitor zapytań, możesz zobaczyć, kiedy dane zapytanie było ostatnio widziane i jakie jest jego maksimum i średni czas wykonania, który może pomóc Ci wybrać najlepsze indeksy dla Twojej tabeli.
Jak wybrać najlepszy indeks do użycia?
Aby wybrać najlepszy indeks do użycia, możesz użyć wbudowanych mechanizmów MySQL. Na przykład możesz użyć wyjaśniacza zapytań - zapytania EXPLAIN. Wyjaśni, jaka tabela jest używana, czy ma partycje, czy nie, jakie indeksy są możliwe do użycia i jaki klucz (indeks) jest używany. Zwróci również długość indeksu i liczbę wierszy zwracanych przez zapytanie:
mysql> EXPLAIN SELECT * FROM demo_table WHERE demo_field = ‘demo’\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: demo_table
partitions: NULL
type: ref
possible_keys: demo_field
key: demo_field
key_len: 1022
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)
W tym przypadku należy pamiętać, że indeksy są często używane, aby pomóc MySQL w wydajnym pobieraniu danych, gdy zestawy danych są większe niż zwykle. Jeśli Twój stół jest mały, możesz nie potrzebować indeksów, ale jeśli zauważysz, że Twoje stoły stają się coraz większe, prawdopodobnie możesz skorzystać z indeksu.
Aby wybrać najlepszy indeks do użycia w konkretnym scenariuszu, należy pamiętać, że indeksy mogą być również główną przyczyną problemów z wydajnością. Należy pamiętać, że to, czy MySQL będzie efektywnie korzystać z indeksów, czy nie, zależy od kilku czynników, w tym projektu zapytania, używanych indeksów, typów używanych indeksów, a także obciążenia bazy danych w czasie wykonywania zapytania oraz inne rzeczy. Oto kilka rzeczy do rozważenia podczas korzystania z indeksów w MySQL:
-
Ile masz danych? Może część z nich jest zbędna?
-
Jakich zapytań używasz? Czy Twoje zapytania będą używać klauzul LIKE? A co z zamawianiem?
-
Jakiego rodzaju indeksu trzeba by użyć, aby poprawić wydajność zapytań?
-
Czy Twoje indeksy byłyby duże czy małe? Czy musisz użyć indeksu na przedrostku kolumny, aby zmniejszyć jej rozmiar?
Warto zauważyć, że prawdopodobnie powinieneś unikać używania wielu typów indeksów (np. indeks B-Tree, UNIQUE INDEX i PRIMARY KEY) również w tej samej kolumnie.
Poprawa wydajności zapytań za pomocą indeksów
Aby poprawić wydajność zapytań za pomocą indeksów, musisz przyjrzeć się swoim zapytaniom — może w tym pomóc instrukcja EXPLAIN. Ogólnie rzecz biorąc, oto kilka rzeczy, które należy wziąć pod uwagę, jeśli chcesz, aby Twoje indeksy poprawiły wydajność zapytań:
-
Poproś bazę danych tylko o to, czego potrzebujesz. W większości przypadków użycie kolumny SELECT będzie szybsze niż użycie SELECT * (tak jest bez użycia indeksów)
-
Indeks B-drzewa może być odpowiedni, jeśli szukasz dokładnych wartości (np. SELECT * FROM demo_table WHERE some_field ='x') lub jeśli chcesz wyszukać wartości za pomocą symboli wieloznacznych (np. SELECT * FROM demo_table WHERE some_field LIKE 'demo%' - w tym przypadku pamiętaj, że użycie zapytań LIKE z czymkolwiek na początku może więcej szkody niż pożytku — unikaj używania zapytań LIKE ze znakiem procentu przed szukanym tekstem — w ten sposób MySQL może nie używać indeksu, ponieważ nie wie, od czego zaczyna się wartość wiersza) — należy jednak pamiętać że indeks B-drzewa może być również używany do porównywania kolumn w wyrażeniach, które używają równego (=), większego niż (>), większego lub równego (>=), mniejszego niż (<), mniejszego lub równego (<=) lub POMIĘDZY operatorami.
-
Indeks FULLTEXT może być odpowiedni, jeśli użyjesz pełnego tekstu (MATCH ... AGAINST( )) zapytań wyszukiwania lub jeśli Twoja baza danych jest zaprojektowana w taki sposób, że używa tylko kolumn tekstowych - indeksy FULLTEXT mogą używać kolumn TEXT, CHAR lub VARCHAR, nie mogą być używane w innych typach kolumn.
-
Indeks pokrywający może być przydatny, jeśli chcesz uruchamiać zapytania bez dodatkowych odczytów I/O na dużych tabelach . Aby utworzyć indeks pokrywający, pokryj klauzule WHERE, GROUP BY i SELECT używane przez zapytanie.
Będziemy dokładniej przyjrzeć się rodzajom indeksów w kolejnych częściach tej serii blogów, ale ogólnie, jeśli używasz zapytań takich jak SELECT * FROM demo_table WHERE some_field ='x' a B-drzewo INDEX może pasować, jeśli używasz zapytań MATCH() AGAINST(), prawdopodobnie powinieneś zajrzeć do indeksu FULLTEXT, jeśli twoja tabela ma bardzo długie wartości wierszy, powinieneś prawdopodobnie zajrzeć do indeksowania części kolumny.
Ile indeksów powinieneś mieć?
Jeśli kiedykolwiek używałeś indeksów do poprawy wydajności zapytań SELECT, prawdopodobnie zadałeś sobie pytanie:ile indeksów powinieneś mieć? Aby to zrozumieć, musisz pamiętać o następujących rzeczach:
-
Indeksy są zwykle najskuteczniejsze w przypadku dużych ilości danych.
-
MySQL używa tylko jednego indeksu na każdą instrukcję SELECT w zapytaniu (podzapytania są postrzegane jako oddzielne instrukcje) - użyj zapytanie EXPLAIN, aby dowiedzieć się, które indeksy są najskuteczniejsze dla używanych zapytań.
-
Indeksy powinny sprawić, że wszystkie instrukcje SELECT będą wystarczająco szybkie, bez narażania zbyt dużej ilości miejsca na dysku — „wystarczająco szybkie” jest jednak względne, więc trzeba poeksperymentować.
Indeksy i silniki pamięci masowej
Mając do czynienia z indeksami w MySQL, pamiętaj również, że mogą istnieć pewne ograniczenia, jeśli używasz różnych silników (na przykład, jeśli używasz MyISAM w przeciwieństwie do InnoDB). Bardziej szczegółowo omówimy w osobnym blogu, ale oto kilka pomysłów:
-
Maksymalna liczba indeksów na tabele MyISAM i InnoDB to 64, maksymalna liczba kolumn na indeks w obu silniki pamięci masowej to 16.
-
Maksymalna długość klucza dla InnoDB to 3500 bajtów - maksymalna długość klucza dla MyISAM to 1000 bajtów.
-
Indeksy pełnotekstowe mają ograniczenia w niektórych silnikach pamięci masowej - na przykład indeksy pełnotekstowe InnoDB mają 36 odrzucanych słów, MyISAM lista stopword jest nieco większa i zawiera 143 stopwords. InnoDB pobiera te odrzucane słowa ze zmiennej innodb_ft_server_stopword_table, podczas gdy MyISAM pobiera te odrzucane słowa z pliku storage/myisam/ft_static.c — wszystkie słowa znalezione w pliku będą traktowane jako odrzucane słowa.
-
MyISAM był jedynym silnikiem przechowywania z obsługą opcji wyszukiwania pełnotekstowego aż do MySQL 5.6 (MySQL 5.6. 4), aby być dokładnym) pojawił się, co oznacza, że InnoDB obsługuje indeksy pełnotekstowe od MySQL 5.6.4. Gdy używany jest indeks FULLTEXT, znajduje on słowa kluczowe w tekście zamiast porównywać wartości bezpośrednio z wartościami w indeksie.
-
Indeksy odgrywają bardzo ważną rolę dla InnoDB - InnoDB blokuje wiersze, gdy ma do nich dostęp, więc zmniejszona liczba Dostęp do wierszy InnoDB może zmniejszyć blokady.
-
MySQL umożliwia używanie zduplikowanych indeksów w tej samej kolumnie.
-
Niektóre silniki pamięci masowej mają pewne domyślne typy indeksów (np. dla silnika pamięci masowej MEMORY domyślnym typem indeksu jest hash )
Podsumowanie
W tej części dotyczącej indeksów w MySQL omówiliśmy kilka ogólnych rzeczy związanych z indeksami w tym systemie zarządzania relacyjnymi bazami danych. W nadchodzących wpisach na blogu omówimy bardziej szczegółowe scenariusze korzystania z indeksów w MySQL, w tym wykorzystanie indeksów w niektórych silnikach pamięci masowej itp. - wyjaśnimy również, w jaki sposób można wykorzystać ClusterControl do osiągnięcia celów wydajnościowych w MySQL.