2012-03-22 11 views
13

Mam tabelę 200k wpisów z kolumnami INT. Chcę utworzyć indeks, aby przyspieszyć zapytania. Oto kwerenda, którą chciałbym wykonać: SELECT A,B,C,D,E FROM table WHERE A=23 and (B=45 or C=43). Stworzyłem następujące indeksy: B, ACD, C, ABC.MySQL. Tworzenie indeksu dla zapytań "OR"

Z poleceniem EXPLAIN znalazłem, że MySQL wybiera indeks ACD. Tak więc zapełniłem tabelę większymi wartościami i zdałem sobie sprawę, że MySQL przełączał się pomiędzy powyższymi indeksami (nie zawsze ten sam).

Ponieważ istnieje wiele wstawek, posiadanie różnych indeksów spowoduje problemy z wydajnością i możemy założyć, że do tej tabeli mają dostęp inne zapytania, które wymagają różnych kolumn, w których każdy indeks ma sens.

Jestem świadomy USE INDEX(), ale chciałbym zrozumieć, czy powinniśmy zaufać MySQL, aby wybrać odpowiedni indeks.

+2

Co rozumiesz przez "możemy założyć, że do tej tabeli mają dostęp inne zapytania, które wymagają różnych kolumn, gdzie każdy INDEX ma sens"? Czy możesz podać przykłady takich zapytań? Czy możesz również podać wynik zapytania 'SHOW INDEXES FROM table'? Indeksy A, AB i AC są z pewnością nadmiarowe: są one już uwzględnione w indeksach odpowiednio dla ACD/ABC, ABC i ACD. Możesz przeczytać o tym, jak MySQL obsługuje indeksy wielu kolumn pod adresem http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html – Daan

+0

Przykładowe zapytanie: 'GET B FROM table WHERE B = 12'. Ok, mogę wyeliminować A, AB, AC (dzięki). Ale nadal nie wyjaśnia powodu używania "ACD". Gdy 'D' nie jest nawet w instrukcji" WHERE ". –

+0

Tak, to jest trochę tajemnicze: dane wyjściowe zapytania "POKAŻ INDEKSY OD ZESTAWU" mogą pomóc zrozumieć, dlaczego tak się dzieje :) – Daan

Odpowiedz

6

powodu OR w SQL, MySQL jest po prostu coraz pierwszy indeks, który zawiera A, który jest ACD.

Doszedłem do wniosku, że sposobem rozwiązania tego problemu za pomocą numeru INDEX jest utworzenie dwóch osobnych zapytań. SELECT A,B,C,D,E FROM table WHERE A=23 AND B=45, który będzie używał INDEX ABC, a następnie SELECT A,B,C,D,E FROM table WHERE A=23 AND C=43, który będzie używał INDEX ACD. Można to zrobić w jednym kroku z (...) UNION (...), który okazuje się szybszy i wykorzystuje tylko INDEKS.

1

Mysql może używać tylko "najbardziej lewej części" złożonego indeksu. To znaczy, jeśli gdzie klauzula wygląda

WHERE A=1 AND B=2 

następnie MySQL może użyć indeksu na A lub AB, ale AB byłoby najlepsze. Nie można użyć ACB, ponieważ indeks jest dzielony przez inną kolumnę

Z podaną klauzulą ​​WHERE, nie sądzę, że silnik zapytań MySQL może wykorzystywać wiele indeksów. Zrobiłbym AB i AC i używając FORCE INDEX, zobacz, który z nich jest szybszy.

Klucz złożony z trzech kolumn nie pomoże w tym przypadku, gdy patrzysz na A i jedną kolumnę. Ten rodzaj klucza pomógłby, gdyby twoje zapytanie używało AND zamiast OR. Indeks na ABC byłby przydatny dla

WHERE A=1 AND B=2 AND C=3 
+2

Tak, z 'AND' używa zapytania ABC zgodnie z oczekiwaniami. Użycie 'A',' AB', 'AC' byłoby zbędne, jak wspomniał @Daan w komentarzu wcześniej. Z dokumentacji MySQL: "Dowolny lewy prefiks indeksu może być użyty przez optymalizator do znalezienia wierszy." INDEX' on (col1, col2, col3), masz indeksowane możliwości wyszukiwania na (col1), (col1, col2), i (col1, col2, col3). " –

+1

To jest pytanie o OR, nie ORAZ. –

Powiązane problemy