Pierwszą rzeczą, którą musisz wiedzieć, jest to, że indeksy to sposób na uniknięcie skanowania pełnej tabeli w celu uzyskania wyniku, którego szukasz.
Istnieją różne rodzaje indeksów, które są zaimplementowane w warstwie pamięci masowej, więc nie ma między nimi żadnego standardu, a ponadto zależą one od używanego silnika pamięci masowej.
InnoDB i indeks B+Tree
W przypadku InnoDB najpopularniejszym typem indeksu jest indeks oparty na B+Drzewo, który przechowuje elementy w posortowanej kolejności. Ponadto nie musisz uzyskiwać dostępu do rzeczywistej tabeli, aby uzyskać zindeksowane wartości, co znacznie przyspiesza powrót zapytania.
„Problem” związany z tym typem indeksu polega na tym, że aby użyć indeksu, musisz wykonać zapytanie o wartość znajdującą się najbardziej po lewej stronie. Jeśli więc indeks ma dwie kolumny, powiedzmy last_name i name_name, kolejność zapytań do tych pól jest bardzo ważna .
Tak więc, biorąc pod uwagę poniższą tabelę:
CREATE TABLE person (
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
INDEX (last_name, first_name)
);
To zapytanie skorzystałoby z indeksu:
SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"
Ale następna nie
SELECT last_name, first_name FROM person WHERE first_name = "Constantine"
Ponieważ pytasz o first_name
pierwsza kolumna i nie jest to pierwsza kolumna z lewej strony w indeksie.
Ten ostatni przykład jest jeszcze gorszy:
SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"
Ponieważ teraz porównujesz skrajną prawą część prawego pola w indeksie.
Indeks skrótu
Jest to inny typ indeksu, który niestety obsługuje tylko zaplecze pamięci. Jest błyskawiczny, ale przydatny tylko do pełnych wyszukiwań, co oznacza, że nie można go używać do operacji takich jak >
, <
lub LIKE
.
Ponieważ działa tylko dla zaplecza pamięci, prawdopodobnie nie będziesz go często używać. Głównym przypadkiem, o którym teraz myślę, jest ten, w którym tworzysz w pamięci tabelę tymczasową z zestawem wyników z innego wyboru i wykonujesz wiele innych wyborów w tej tabeli tymczasowej przy użyciu indeksów mieszających.
Jeśli masz duży VARCHAR
pole, możesz "emulować" użycie indeksu skrótu podczas korzystania z B-Tree, tworząc kolejną kolumnę i zapisując w niej skrót o dużej wartości. Załóżmy, że przechowujesz adres URL w polu, a wartości są dość duże. Możesz także utworzyć pole liczb całkowitych o nazwie url_hash
i użyj funkcji skrótu, takiej jak CRC32
lub jakakolwiek inna funkcja skrótu do mieszania adresu URL podczas wstawiania go. A następnie, gdy potrzebujesz zapytać o tę wartość, możesz zrobić coś takiego:
SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");
Problem z powyższym przykładem polega na tym, że ponieważ CRC32
funkcja generuje dość mały hash, będziesz miał dużo kolizji w wartościach haszowanych. Jeśli potrzebujesz dokładnych wartości, możesz rozwiązać ten problem, wykonując następujące czynności:
SELECT url FROM url_table
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";
Nadal warto haszować, nawet jeśli liczba kolizji jest wysoka, ponieważ wykonasz tylko drugie porównanie (łańcuchowe) z powtarzającymi się haszami.
Niestety, używając tej techniki, nadal musisz trafić w tabelę, aby porównać url
pole.
Podsumuj
Kilka faktów, które możesz wziąć pod uwagę za każdym razem, gdy chcesz porozmawiać o optymalizacji:
-
Porównanie liczb całkowitych jest znacznie szybsze niż porównywanie ciągów. Można to zilustrować przykładem emulacji indeksu skrótu w
InnoDB
. -
Być może dodanie dodatkowych kroków w procesie sprawi, że będzie on szybszy, a nie wolniejszy. Można to zilustrować faktem, że możesz zoptymalizować
SELECT
dzieląc go na dwa kroki, sprawiając, że pierwszy przechowuje wartości w nowo utworzonej tabeli w pamięci, a następnie wykonuje cięższe zapytania w tej drugiej tabeli.
MySQL ma też inne indeksy, ale myślę, że B+Tree jest najczęściej używany, a hash jest dobrze wiedzieć, ale możesz znaleźć inne indeksy w Dokumentacja MySQL .
Gorąco polecam lekturę książki "High Performance MySQL", powyższa odpowiedź była zdecydowanie oparta na rozdziale o indeksach.