Mam problemy z wydajnością niektórych zapytań do bazy danych, które mają duże możliwe zestawy wyników.
Pytanie, o którym mowa, mam trzy AND
s w klauzuli WHERE
Czy kolejność klauzul ma znaczenie?
Tak jak w przypadku, jeśli najpierw wstawię klauzulę ASI_EVENT_TIME (ponieważ spowoduje to usunięcie większości wyników z którejkolwiek z klauzul).
Czy poprawi to czas działania zapytania?
PYTANIE:
SELECT DISTINCT activity_seismo_info.*
FROM `activity_seismo_info`
WHERE
activity_seismo_info.ASI_ACTIVITY_ID IS NOT NULL AND
activity_seismo_info.ASI_SEISMO_ID IN (43,44,...,259) AND
(
activity_seismo_info.ASI_EVENT_TIME>='2011-03-10 00:00:00' AND
activity_seismo_info.ASI_EVENT_TIME<='2011-03-17 23:59:59'
)
ORDER BY activity_seismo_info.ASI_EVENT_TIME DESC
OBJAŚNIJ zapytanie:
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+
| 1 | SIMPLE | act...o | range | act...o_FI_1,act...o_FI_2 | act...o_FI_1 | 5 | NULL | 65412 | Using where; Using filesort |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+
Za pomocą:
PHP 5.2
MySQL 5.0.51a-3ubuntu5.4
Propel 1.3
Symfony 1.2.5
mysql
performance
mysql-5
Patrick
źródło
źródło
order by
należy do bazy danych.Odpowiedzi:
Nie sądzę. Optymalizator zapytań powinien być wystarczająco sprytny.
Możesz spróbować zmienić kolejność klauzul WHERE i przekonać się, że WYJAŚNIENIA mówią ci to samo w każdym przypadku.
O tym, co można zrobić, aby zoptymalizować to zapytanie: Czy istnieje indeks w ASI_EVENT_TIME? (Myślę, że jest to najbardziej istotne dla tego zapytania, ponieważ sortujesz również wyniki za jego pomocą).
Czy istnieją indeksy w pozostałych dwóch polach (ASI_SEISMO_ID i ASI_ACTIVITY_ID)?
Byłoby pomocne, gdybyś opublikował strukturę tabeli.
źródło
Z dokumentacji :
Tak, powinien być taki sam, jak kolejność kolumn w indeksie złożonym .
źródło
WHERE c = 'foo' AND a = 'bar' AND b = 'foobar'
a indeks nadal kwalifikuje się do użycia.Nie, to nie ma znaczenia.
Optymalizator wykonuje kilka prostych przekształceń bezpośrednio po przeanalizowaniu kodu SQL - jest to jedna z nich.
źródło
optymalizuje to samo co
Jednak,
Nie można zoptymalizować obu części. Na przykład,
nie może dobrze wykorzystać INDEKSU (a, b) lub INDEKSU (b, a)
Aby wyrazić to inaczej, najpierw używane są wszystkie testy „=” ORAZ razem w klauzuli WHERE, a następnie można obsłużyć jedno nie - „=” (IN, MIĘDZY,> itd.). Nie można skutecznie zoptymalizować więcej niż jednego.
Twoje zapytanie zawiera 3 takie klauzule.
Jak się okazuje, INDEKS (EVENT_TIME) jest prawdopodobnie najbardziej przydatny - pomoże w jednym z AND, i może być użyty do uniknięcia „sortowania plików” dla ORDER BY.
Jeśli nie ma zduplikowanych wierszy (dlaczego, u licha, miałby być?), Pozbądź się DISTINCT. To powoduje jeszcze większy wysiłek.
Zadawaj pytania POKAŻ TWORZENIE TABELI i STATUS POKAŻU TABELI, zadając pytania dotyczące wydajności.
Aktualizacja ... Nowsze wersje (np. MySQL 5.7) mogą, w niektórych sytuacjach, traktować
IN( list of constants )
prawie jak=
. Aby grać bezpiecznie, trzymaj się tej kolejności (każda część jest opcjonalna):=
.INs
.źródło
MySQL, w którym dokument optymalizacji mówi:
W ten sposób racjonalne jest, aby optymalizator zapytań pomijał kolejność JAK użyliśmy kolumn w zapytaniu (Nie tylko MySQL, ale SQL jest językiem deklaratywnym i musi robić to, co chcemy, a nie to, co chcemy).
Jednak nadal lubię mieć taki sam rodzaj kolumn klucza złożonego w zapytaniu, ale czasami jest to nieuniknione, na przykład, gdy używamy ORM lub ActiveRecord, w niektórych ramach, takich jak yii2, dostosowywanie kryteriów relacji zostanie dołączone na końcu warunek „włączony”, ale nadal potrzebujemy możliwości QueryBuilders w różnych częściach aplikacji.
źródło
DOWOLNE pole, które jest używane w klauzulach WHERE / HAVING i ma wysoką selektywność (liczba unikalnych wartości / całkowita liczba rekordów> 10% ~ 20%) MUSI być indeksowane.
Jeśli więc
ASI_EVENT_TIME
kolumna ma wiele możliwych wartości, najpierw zindeksuj je wszystkie. Następnie, jak powiedział @ypercube, spróbuj je zmienić i zobacz, co mówi WYJAŚNIENIE. Powinny być takie same.Dodatkowo, chcesz spojrzeć na indeksowanie filtrów LIKE SQL . Chociaż nie jest to odpowiedź na pytanie, ale nadal dowiesz się, jak indeksowanie działa pod maską.
* Edycja: zapoznaj się z linkami podanymi poniżej w komentarzach, aby dowiedzieć się więcej o indeksowaniu.
źródło