Dane wyjściowe EXPLAIN sugerują, że mój indeks nie jest używany

9

Skonfigurowałem tabelę z indeksem tylko na done_status (done_status = INT):

wprowadź opis zdjęcia tutaj

Kiedy używam:

EXPLAIN SELECT * FROM reminder  WHERE done_status=2

Odzyskuję to:

id select_type typ tabeli możliwe klucze klucze key_len ref wiersze Extra
1 PROSTE przypomnienie WSZYSTKO done_status NULL NULL NULL 5 Używanie gdzie

Ale kiedy wydam to polecenie:

EXPLAIN SELECT * FROM reminder  WHERE done_status=1

Otrzymuję następujące informacje:

id select_type typ tabeli możliwe klucze klucze key_len ref wiersze Extra
1 SIMPLE przypomnienie ref done_status done_status 4 const 2   

Do EXPLAINpokazuje mi, że używa 5 rzędów, po raz drugi 2 rzędy.

Nie sądzę, że indeks jest używany, jeśli dobrze go zrozumiałem, powinien dać mi 3 wiersze. Co robię źle?

SHOW INDEX FROM reminder:

Tabela Non_unique nazwa_klucza Seq_in_index nazwa_kolumny Sortowanie Liczność Podpunkt Pakowane Null Typ indeksu Komentarz Indeks
przypomnienie 1 done_status 1 done_status A 5 NULL NULL BTREE

wyjaśnij rozszerzone:

id select_type typ tabeli możliwy_klucz klucz key_len ref wiersze filtrowane Extra
1 PROSTE przypomnienie przypomnienie done_status done_status 4 const 2 100.00

show warnings nie okazał niczego interesującego.

TasostheGreat
źródło
Zaufaj mi, że indeks działa. Ale nie widzę nic łatwo na twoim zrzucie ekranu - czy możesz zrobić „pokaż indeks ze swojego stołu”
tak, zredagowałem moje pytanie
użyj glorify \ G dla schematu i wyjaśnij wynik planu, powinien być bardziej czytelny
ajreal
Zainteresowany możesz powtórzyć z „wyjaśnij rozszerzone” i „pokaż ostrzeżenia”, to pokaże faktyczny mysql SQL wybiera
@ajreal co to jest gloryfikacja?

Odpowiedzi:

4

Nie rozumiesz, czym jest pole „wiersze”. Jest to liczba wierszy, które szacuje mysql, które powinien odczytać, aby spełnić twoje zapytanie. Ta wartość może być dość niedokładna. Nie oznacza to, że jest to liczba wierszy w wyniku - ani faktyczna liczba wierszy odczytanych przez mysql


źródło
Więc? Gdzie powiedziałem, że tak? Co wybierze optymalizator? Indeks nadal działa.
@ajreal Nie oznacza to jednak, że indeks jest zepsuty. Po prostu optymalizator wybiera (w swojej opinii) najbardziej efektywny sposób zapytania danych. Zakładałem, że OP spodziewał się, że kolumna wierszy w WYJAŚNIENIU będzie dokładna. Nie oznacza to, że indeks jest zepsuty - po prostu mysql zdecyduje się go nie używać (prawdopodobnie).
1
@ajreal: Brakuje mi czegoś w twoich punktach. Kolumna wierszy wyjaśnienia nie ma nic wspólnego z indeksami, prawda? Mysql nie korzysta z indeksu (być może wszystkie dane są na jednej stronie). Nie jesteś pewien, czy rozumiem twój punkt widzenia? Optymalizacja zapytania w tabeli 5-wierszowej przyniesie pewne „dziwne” wyniki, ponieważ nie ma znaczenia, w jaki sposób optymalizujesz.
W takim przypadku, kogo obchodzi, jaki indeks wybiera optymalizator? Z samym indeksem nie ma nic złego, ponieważ optymalizator czuł, że go nie potrzebuje - co to ma znaczenie?
3

Pierwsza wersja wykonania na pewno nie korzysta z indeksu,
może to być schemat informacyjny. Statystyki w indeksie nie nadążają za danymi po niektórych operacjach zapisu lub do tabeli nie można uzyskać dostępu przez długi czas.

jak wyjaśnić tutaj: - Skąd MySQL Query Optimizer odczytuje statystyki indeksu?

w przypadku drugiego planu wykonania wydaje się, że informacja_schema.statistics już nadrobiła zaległości i rozwiązała problem liczności NULL.

Dlatego wykonuje zapytanie zgodnie z optymalizatorem indeksu.

W przypadku tabeli z małymi rzędami nie ma to większego znaczenia.
Ale dane będą rosły, programista powinien zawsze to sprawdzić
i przeprowadzić niezbędną analizę tabeli, gdy liczebność napotkania w indeksie jest zerowa.

ajreal
źródło
0

Pierwszy plan wykonania nie korzysta z indeksu.

Ze strony referencyjnej MySQL :

Czasami MySQL nie używa indeksu, nawet jeśli jest on dostępny. Jedną z okoliczności, w których ma to miejsce, jest oszacowanie przez optymalizatora, że ​​użycie indeksu wymagałoby od MySQL dostępu do bardzo dużego odsetka wierszy w tabeli. (W takim przypadku skanowanie tabeli prawdopodobnie będzie znacznie szybsze, ponieważ wymaga mniej prób). Jednak jeśli takie zapytanie używa LIMIT do pobrania tylko niektórych wierszy, MySQL i tak używa indeksu, ponieważ może znacznie szybciej znaleźć kilka wierszy do zwrócenia w wyniku.

Jeśli twoja tabela ma tylko 5 wierszy, a zapytanie wybiera 3 z nich, wówczas optymalizator MySQL zakłada, że ​​bardziej wydajne jest skanowanie całej tabeli.

Matthew Sammut
źródło