MariaDB
 sql >> Baza danych >  >> RDS >> MariaDB

Przewodnik po indeksach MySQL

Kiedy wspomniana jest optymalizacja zapytań MySQL, indeksy są jedną z pierwszych rzeczy, które są omawiane. Dzisiaj postaramy się zobaczyć, dlaczego są tak ważne.

Co to są indeksy?

Na ogół indeks jest alfabetyczną listą rekordów z odniesieniami do stron, na których są wymienione. W MySQL indeks to struktura danych używana do szybkiego wyszukiwania wierszy. Indeksy są również nazywane kluczami, a klucze te mają kluczowe znaczenie dla dobrej wydajności - w miarę wzrostu danych potrzeba prawidłowego korzystania z indeksów może stawać się coraz ważniejsza. Korzystanie z indeksów jest jednym z najpotężniejszych sposobów na poprawę wydajności zapytań — jeśli indeksy są używane prawidłowo, wydajność zapytań może wzrosnąć dziesiątki, a nawet setki razy.

Dzisiaj postaramy się wyjaśnić podstawowe zalety i wady korzystania z indeksów w MySQL. Pamiętaj, że same indeksy MySQL zasługują na całą książkę, więc ten post nie obejmie absolutnie wszystkiego, ale będzie dobrym punktem wyjścia. Dla tych, którzy są zainteresowani tym, jak indeksy działają na głębszym poziomie, przeczytanie książki Relational Database Index Design and the Optimizers autorstwa Tapio Lahdenmäki i Michaela Leacha powinno zapewnić więcej informacji.

Korzyści z używania indeksów

Istnieje kilka głównych korzyści z używania indeksów w MySQL, a są to następujące:

  • Indeksy pozwalają szybko znaleźć wiersze pasujące do klauzuli WHERE;
  • Indeksy mogą pomóc zapytaniom uniknąć przeszukiwania niektórych wierszy, zmniejszając w ten sposób ilość danych, które serwer musi zbadać - jeśli istnieje wybór między wieloma indeksami, MySQL zwykle używa najbardziej selektywnego indeksu, czyli takiego indeks, który znajduje najmniejszą liczbę wierszy;
  • Indeksy mogą być używane do pobierania wierszy z innych tabel w operacjach JOIN;
  • Indeksy mogą służyć do znajdowania minimalnej lub maksymalnej wartości określonej kolumny, która korzysta z indeksu;
  • Indeksy mogą być używane do sortowania lub grupowania tabeli, jeśli operacje są wykonywane na skrajnym lewym prefiksie indeksu — podobnie, skrajny lewy prefiks indeksu wielokolumnowego może być również używany przez optymalizator zapytań wyszukiwać wiersze;
  • Indeksy mogą być również używane do zapisywania operacji we/wy dysku — gdy używany jest indeks pokrywający, zapytanie może zwrócić wartości bezpośrednio ze struktury indeksu, zapisując dyskowe operacje we/wy.

Podobnie istnieje wiele typów indeksów:

  • INDEX to rodzaj indeksu, w którym wartości nie muszą być unikalne. Ten typ indeksu akceptuje wartości NULL;
  • UNIKALNY INDEKS jest często używany do usuwania zduplikowanych wierszy z tabeli - ten typ indeksu pozwala programistom wymusić unikalność wartości wierszy;
  • INDEKS PEŁNOTEKSTOWY to indeks stosowany w polach wykorzystujących 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;
  • DESCENDING INDEX to indeks, który przechowuje wiersze w porządku malejącym - optymalizator zapytań wybierze ten typ indeksu, gdy zapytanie będzie żądać kolejności malejącej. Ten typ indeksu został wprowadzony w MySQL 8.0;
  • KLUCZ PODSTAWOWY jest również indeksem. W skrócie KLUCZ PODSTAWOWY to kolumna lub zestaw kolumn, które identyfikują każdy wiersz w tabeli - 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 PRIMARY KEY nie mogą zostać zmienione.

Teraz spróbujemy omówić zarówno zalety, jak i wady używania indeksów w MySQL. Zaczniemy od prawdopodobnie najczęściej omawianej zalety - przyspieszenia zapytań pasujących do klauzuli WHERE.

Przyspieszenie zapytań pasujących do klauzuli WHERE

Indeksy są często używane do przyspieszenia zapytań, które pasują do klauzuli WHERE. Powód, dla którego indeks przyspiesza takie operacje wyszukiwania, jest dość prosty — zapytania korzystające z indeksu unikają pełnego skanowania tabeli.

W celu przyspieszenia zapytań, które pasują do klauzuli WHERE, możesz skorzystać z instrukcji EXPLAIN w MySQL. Instrukcja EXPLAIN SELECT powinna zapewnić pewien wgląd w to, w jaki sposób optymalizator zapytań MySQL wykonuje zapytanie — może również pokazać, czy dane zapytanie używa indeksu, czy nie i jakiego indeksu używa. Spójrz na następujące wyjaśnienie zapytania:

mysql> EXPLAIN SELECT * FROM demo_table WHERE field_1 = “Demo” \G;

*************************** 1. row ***************************

<...>

possible_keys: NULL

key: NULL

key_len: NULL

<...>

Powyższe zapytanie nie używa indeksu. Jeśli jednak dodamy indeks do „field_1”, indeks zostanie pomyślnie użyty:

mysql> EXPLAIN SELECT * FROM demo_table WHERE field_1 = “Demo” \G;

*************************** 1. row ***************************

<...>

possible_keys: field_1

key: field_1

key_len: 43

<...>

Kolumna possible_keys opisuje możliwe indeksy, które MySQL może wybrać, kolumna klucza opisuje faktycznie wybrany indeks, a kolumna key_len opisuje długość wybranego klucza.

W tym przypadku MySQL wykonałby wyszukiwanie wartości w indeksie i zwróciłby wszystkie wiersze zawierające określoną wartość - w rezultacie zapytanie byłoby szybsze. Chociaż indeksy pomagają niektórym zapytaniom działać szybciej, należy pamiętać o kilku rzeczach, jeśli chcesz, aby indeksy pomagały w wykonywaniu zapytań:

  • Izoluj swoje kolumny — MySQL nie może używać indeksów, jeśli kolumny, w których indeksy są używane, nie są izolowane. Na przykład takie zapytanie nie używa indeksu:
    SELECT field_1 FROM demo_table WHERE field_1 + 5 = 10;

Aby rozwiązać ten problem, zostaw w spokoju kolumnę, która występuje po klauzuli WHERE - maksymalnie uprość zapytanie i wyizoluj kolumny;

  • Unikaj używania zapytań LIKE z poprzedzającym go znakiem wieloznacznym — w tym przypadku MySQL nie użyje indeksu, ponieważ poprzedzający go symbol wieloznaczny oznacza, że ​​przed tekstem może znajdować się cokolwiek. Jeśli musisz używać zapytań LIKE z symbolami wieloznacznymi i chcesz, aby zapytania korzystały z indeksów, upewnij się, że symbol wieloznaczny znajduje się na końcu instrukcji wyszukiwania.

Oczywiście przyspieszenie zapytań, które pasują do klauzuli WHERE, można również wykonać na inne sposoby (na przykład partycjonowanie), ale dla uproszczenia nie będziemy się tym zagłębiać w tym poście.

Możemy być jednak zainteresowani różnymi rodzajami indeksów, więc przyjrzymy się temu teraz.

Pozbywanie się zduplikowanych wartości w kolumnie — UNIKALNE indeksy

Celem UNIQUE indeksu w MySQL jest wymuszenie unikalności wartości w kolumnie. Aby użyć indeksu UNIQUE, uruchom zapytanie CREATE UNIQUE INDEX:

CREATE UNIQUE INDEX demo_index ON demo_table(demo_column);

You can also create a unique index when you create a table:

CREATE TABLE demo_table (
`demo_column` VARCHAR(100) NOT NULL,
UNIQUE KEY(demo_column)
);

To wystarczy, aby dodać unikalny indeks do tabeli. Teraz, gdy spróbujesz dodać zduplikowaną wartość do tabeli, MySQL powróci z następującym błędem:

#1062 - Duplicate entry ‘Demo’ for key ‘demo_column’

Pełnotekstowe indeksy

Indeks FULLTEXT to taki indeks, który jest stosowany do kolumn, które wykorzystują możliwości wyszukiwania pełnotekstowego. Ten typ indeksu ma wiele unikalnych możliwości, w tym odrzucane słowa i tryby wyszukiwania.

Lista odrzucanych słów InnoDB ma 36 słów, podczas gdy lista odrzucanych słów MyISAM ma 143. W InnoDB odrzucane słowa pochodzą z tabeli ustawionej w zmiennej innodb_ft_user_stopword_table, w przeciwnym razie, jeśli ta zmienna nie jest ustawiona, są wyprowadzane ze zmiennej innodb_ft_server_stopword_table. Jeśli żadna z tych dwóch zmiennych nie jest ustawiona, InnoDB używa wbudowanej listy. Aby zobaczyć domyślną listę odrzucanych słów InnoDB, przeprowadź zapytanie do tabeli INNODB_FT_DEFAULT_STOPWORD.

W MyISAM odrzucane słowa pochodzą z pliku storage/myisam/ft_static.c. Zmienna ft_stopword_file umożliwia zmianę domyślnej listy odrzucanych słów. Stopwords zostanie wyłączone, jeśli ta zmienna jest ustawiona na pusty ciąg, ale pamiętaj, że jeśli ta zmienna definiuje plik, zdefiniowany plik nie jest analizowany pod kątem komentarzy - MyISAM potraktuje wszystkie słowa znalezione w pliku jako stopwords.

Indeksy FULLTEXT słyną również z unikalnych trybów wyszukiwania:

  • Jeśli zostanie uruchomione zapytanie FULLTEXT bez modyfikatorów, zostanie aktywowany tryb języka naturalnego. Tryb języka naturalnego można również aktywować za pomocą modyfikatora W TRYBIE JĘZYKA NATURALNEGO;
  • Modyfikator WITH QUERY EXPANSION włącza tryb wyszukiwania z rozszerzeniem zapytania. Taki tryb wyszukiwania działa poprzez dwukrotne wykonanie wyszukiwania, a gdy wyszukiwanie jest uruchamiane po raz drugi, zestaw wyników zawierałby kilka najbardziej odpowiednich dokumentów z pierwszego wyszukiwania. Ogólnie rzecz biorąc, ten modyfikator jest przydatny, gdy użytkownik ma pewną dorozumianą wiedzę (na przykład użytkownik może wyszukać „baza danych” i mieć nadzieję, że w zestawie wyników zobaczy „InnoDB” i „MyISAM”);
  • Modyfikator IN BOOLEAN MODE umożliwia wyszukiwanie za pomocą operatorów logicznych. Na przykład operatory +, - lub * wykonywałyby różne zadania — operator + określałby, że wartość musi znajdować się w wierszu, operator - określałby, że wartość nie może istnieć, a operator * będzie działał jako symbol wieloznaczny.

Zapytanie używające indeksu FULLTEXT wygląda tak:

SELECT * FROM demo_table WHERE MATCH(demo_field) AGAINST(‘value’ IN NATURAL LANGUAGE MODE);

Pamiętaj, że indeksy FULLTEXT są generalnie przydatne dla operacji MATCH() AGAINST() - nie dla operacji WHERE, co oznacza, że ​​jeśli klauzula WHERE zostałaby użyta, przydatność korzystania z różnych typów indeksów nie zostałaby wyeliminowana.

Warto również wspomnieć, że indeksy FULLTEXT mają minimalną długość znaków. W InnoDB wyszukiwanie FULLTEXT można przeprowadzić tylko wtedy, gdy zapytanie wyszukiwania składa się z co najmniej trzech znaków — ten limit jest zwiększony do czterech znaków w silniku pamięci MyISAM.

Zstępujące indeksy

Indeks DESCENDING to taki indeks, w którym InnoDB przechowuje wpisy w porządku malejącym - optymalizator zapytań użyje takiego indeksu, gdy zapytanie będzie żądać kolejności malejącej. Taki indeks można dodać do kolumny, uruchamiając zapytanie jak poniżej:

CREATE INDEX descending_index ON demo_table(column_name DESC);

Indeks rosnący można również dodać do kolumny - wystarczy zastąpić DESC przez ASC.

KLUCZE PODSTAWOWE

KLUCZ PODSTAWOWY służy jako unikalny identyfikator dla każdego wiersza w tabeli. Kolumna z PRIMARY KEY musi zawierać unikalne wartości — nie można też używać wartości NULL. Jeśli zduplikowana wartość zostanie dodana do kolumny, która ma PRIMARY KEY, MySQL odpowie z błędem #1062:

#1062 - Duplicate entry ‘Demo’ for key ‘PRIMARY’

Jeśli do kolumny zostanie dodana wartość NULL, MySQL odpowie z błędem #1048:

#1048 - Column ‘id’ cannot be null

Indeksy podstawowe są również czasami nazywane indeksami klastrowymi (omówimy je później).

Można także tworzyć indeksy dla wielu kolumn naraz — takie indeksy są nazywane indeksami wielokolumnowymi.

Indeksy wielokolumnowe

Indeksy w wielu kolumnach są często źle rozumiane – czasami programiści i administratorzy baz danych indeksują wszystkie kolumny osobno lub indeksują je w niewłaściwej kolejności. Aby zapytania wykorzystujące indeksy wielokolumnowe były jak najbardziej efektywne, pamiętaj, że kolejność kolumn w indeksach wykorzystujących więcej niż jedną kolumnę jest jedną z najczęstszych przyczyn nieporozumień w tej przestrzeni - ponieważ nie ma „tam ani autostradą”. ” rozwiązania kolejności indeksów, należy pamiętać, że prawidłowa kolejność indeksów wielokolumnowych zależy od zapytań, które używają indeksu. Chociaż może się to wydawać dość oczywiste, pamiętaj, że kolejność kolumn ma kluczowe znaczenie w przypadku indeksów wielokolumnowych – wybierz taką kolejność kolumn, aby była jak najbardziej selektywna dla zapytań, które będą wykonywane najczęściej.

W celu zmierzenia selektywności dla określonych kolumn należy uzyskać stosunek liczby odrębnych wartości indeksowanych do całkowitej liczby wierszy w tabeli - kolumna o wyższej selektywności powinna być pierwszą .

Czasami trzeba również zaindeksować bardzo długie kolumny znaków, aw takim przypadku często można zaoszczędzić czas i zasoby, indeksując kilka pierwszych znaków — przedrostek — zamiast całej wartości.

Indeksy przedrostków

Indeksy prefiksowe mogą być przydatne, gdy kolumny zawierają bardzo długie wartości łańcuchowe, co oznaczałoby, że dodanie indeksu do całej kolumny zajęłoby dużo miejsca na dysku. MySQL pomaga rozwiązać ten problem, umożliwiając indeksowanie tylko prefiksu wartości, co z kolei zmniejsza rozmiar indeksu. Spójrz:

CREATE TABLE `demo_table` (
`demo_column` VARCHAR(100) NOT NULL,
INDEX(demo_column(10))
);

Powyższe zapytanie utworzyłoby indeks prefiksu w kolumnie demonstracyjnej, indeksując tylko pierwsze 10 znaków wartości. Możesz także dodać indeks przedrostka do istniejącej tabeli:

CREATE INDEX index_name ON table_name(column_name(length));

Tak więc, na przykład, jeśli chcesz zaindeksować pierwszych 5 znaków kolumny demo w tabeli demo_table, możesz uruchomić następujące zapytanie:

CREATE INDEX demo_index ON demo_table(demo_column(5));

Powinieneś wybrać przedrostek, który jest wystarczająco długi, aby zapewnić selektywność, ale także wystarczająco krótki, aby zapewnić miejsce. Łatwiej to powiedzieć niż zrobić — musisz poeksperymentować i znaleźć rozwiązanie, które będzie dla Ciebie odpowiednie.

Pokrywa indeksy

Indeks pokrywający „pokrywa” wszystkie pola wymagane do wykonania zapytania. Innymi słowy, gdy wszystkie pola w zapytaniu są objęte indeksem, używany jest indeks pokrywający. Na przykład dla zapytania takiego jak:

SELECT id, title FROM demo_table WHERE id = 1;

Indeks pokrywający może wyglądać tak:

INDEX index_name(id, title);

Jeżeli chcesz się upewnić, że zapytanie korzysta z indeksu pokrywającego, wydaj dla niego instrukcję EXPLAIN, a następnie spójrz na kolumnę Extra. Na przykład, jeśli twoja tabela ma indeks wielokolumnowy na id i tytule, a zapytanie, które ma dostęp tylko do tych dwóch kolumn, zostanie wykonane, MySQL użyje indeksu:

mysql> EXPLAIN SELECT id, title FROM demo_table \G;

*************************** 1. row ***************************

<...>

type: index

key: index_name

key_len: 5

rows: 1000

Extra: Using index

<...>

Pamiętaj, że indeks pokrywający musi przechowywać wartości z kolumn, które obejmuje. Oznacza to, że MySQL może używać tylko indeksów B-Tree do obsługi zapytań, ponieważ inne rodzaje indeksów nie przechowują tych wartości.

Zgrupowane, drugorzędne indeksy i liczność indeksu

Gdy omawiamy indeksy, możesz również usłyszeć terminy grupowane, indeksy drugorzędne i kardynalność indeksów. Mówiąc prościej, indeksy klastrowe to podejście do przechowywania danych, a wszystkie indeksy inne niż indeksy klastrowe są indeksami drugorzędnymi. Z drugiej strony liczność indeksu to liczba unikalnych wartości w indeksie.

Indeks klastrowy przyspiesza zapytania, ponieważ bliskie wartości są również przechowywane blisko siebie na dysku, ale jest to również powód, dla którego możesz mieć tylko jeden indeks klastrowy w tabeli.

Indeks wtórny to dowolny indeks, który nie jest indeksem podstawowym. Taki indeks może mieć duplikaty.

Wady korzystania z indeksów

Korzystanie z indeksów z pewnością ma swoje zalety, ale nie możemy zapominać, że indeksy mogą być również jedną z głównych przyczyn problemów w MySQL. Niektóre wady korzystania z indeksów są następujące:

  • Indeksy mogą obniżyć wydajność niektórych zapytań — chociaż indeksy mają tendencję do przyspieszania wydajności zapytań SELECT, spowalniają wydajność zapytań INSERT, UPDATE i DELETE, ponieważ po zaktualizowaniu danych indeks również musi być aktualizowany razem z nim:każda operacja, która wymaga manipulowania indeksami, będzie wolniejsza niż zwykle;
  • Indeksy zajmują miejsce na dysku — indeks zajmuje własną przestrzeń, więc zindeksowane dane również zajmą więcej miejsca na dysku;
  • Zbędne i zduplikowane indeksy mogą być problemem - MySQL pozwala na tworzenie zduplikowanych indeksów na kolumnie i nie „chroni Cię” przed popełnieniem takiego błędu. Spójrz na ten przykład: 
    CREATE TABLE `demo_table` (
    
    `id` INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    
    `column_2` VARCHAR(10) NOT NULL,
    
    `column_3` VARCHAR(10) NOT NULL,
    
    INDEX(id),
    
    UNIQUE(id)
    
    );

Niedoświadczony użytkownik może pomyśleć, że to zapytanie powoduje automatyczne zwiększenie kolumny identyfikatora, a następnie dodaje indeks do kolumny i sprawia, że ​​kolumna nie akceptuje zduplikowanych wartości. Jednak tak się nie dzieje. W tym przypadku ta sama kolumna ma trzy indeksy:zwykły INDEX, a ponieważ MySQL implementuje zarówno ograniczenia PRIMARY KEY, jak i UNIQUE z indeksami, dodaje to dwa dodatkowe indeksy do tej samej kolumny!

Wnioski

Podsumowując, indeksy w MySQL mają swoje własne miejsce — indeksy mogą być używane w wielu scenariuszach, ale każdy z tych scenariuszy użycia ma swoje wady, które należy wziąć pod uwagę, aby w pełni wykorzystać indeksy, które są w użyciu.

Aby dobrze korzystać z indeksów, sprofiluj swoje zapytania, spójrz jakie masz opcje jeśli chodzi o indeksy, poznaj ich zalety i wady, zdecyduj, jakich indeksów potrzebujesz w oparciu o swoje wymagania i po zaindeksowaniu kolumn upewnij się, że Twoje indeksy są faktycznie używane przez MySQL. Jeśli prawidłowo zindeksowałeś swój schemat, wydajność zapytań powinna się poprawić, ale jeśli czas odpowiedzi Cię nie satysfakcjonuje, sprawdź, czy można stworzyć lepszy indeks, aby go ulepszyć.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Instalowanie Laravel na Ubuntu z obsługą Apache, MariaDB i PHP

  2. Porównanie odzyskiwania do punktu w czasie Amazon RDS z ClusterControl

  3. 3 sposoby na uzyskanie nazwy dnia z randki w MariaDB

  4. Laravel:Określony klucz był za długi; maksymalna długość klucza to 767 bajtów

  5. Porównanie ofert Galera Cluster Cloud:część pierwsza Amazon AWS