Czy istnieje różnica w wydajności między tymi dwoma przykładowymi zapytaniami?
Zapytanie 1:
select count(*)
from table1 a
join table2 b
on b.key_col=a.key_col
where b.tag = 'Y'
Zapytanie 2;
select count(*)
from table1 a
join table2 b
on b.key_col=a.key_col
and b.tag = 'Y'
Zauważ, że jedyną różnicą jest umieszczenie warunku uzupełniającego; pierwszy używa WHERE
klauzuli, a drugi dodaje warunek do ON
klauzuli.
Kiedy uruchamiam te zapytania w moim systemie Teradata, plany wyjaśniania są identyczne, a krok DOŁĄCZ pokazuje w każdym przypadku dodatkowy warunek. Jednak w przypadku tego pytania SO dotyczącego MySQL jedna z odpowiedzi sugerowała, że preferowany jest drugi styl, ponieważ WHERE
przetwarzanie następuje po dokonaniu połączeń.
Czy przy kodowaniu takich zapytań należy przestrzegać ogólnej zasady? Domyślam się, że musi to zależeć od platformy, ponieważ oczywiście nie ma to wpływu na moją bazę danych, ale być może jest to tylko funkcja Teradata. A jeśli zależy to od platformy, bardzo chciałbym uzyskać kilka odniesień do dokumentacji; Naprawdę nie wiem, czego szukać.
źródło
Odpowiedzi:
Według rozdziału 9 (Parser i optymalizator), Sasha Pachev , strona 172 książki Understanding MySQL Internal.
oto podział oceny zapytania jako następujące zadania:
ORDER BY
iGROUP BY
.Na tej samej stronie jest napisane:
EPILOG
Ze względu na obecne klucze, ilość danych i wyrażenie zapytania, połączenia MySQL mogą czasami robić rzeczy dla naszego własnego dobra (lub wrócić do nas) i dawać wyniki, których się nie spodziewaliśmy i których nie możemy szybko wyjaśnić.
O tym dziwactwie pisałem już wcześniej
Jan 23, 2013
: Problem z zagnieżdżonymi zapytaniami UPDATEFeb 22, 2011
: Problem z podzapytaniem MySQLponieważ Optymalizator zapytań MySQL może spowodować odrzucenie niektórych kluczy podczas oceny zapytania.
Komentarz @ Phila pomaga mi zobaczyć, jak opublikować tę odpowiedź (+1 za komentarz @ Phila)
Komentarz @ ypercube (+1 również dla tego) jest kompaktową wersją mojego postu, ponieważ Optymalizator zapytań MySQL jest prymitywny. Niestety musi tak być, ponieważ dotyczy zewnętrznych silników pamięci masowej.
WNIOSEK
Jeśli chodzi o twoje pytanie, Optymalizator zapytań MySQL określałby wskaźniki wydajności każdego zapytania po jego zakończeniu
Prawdopodobnie musiałbyś wymusić kolejność wykonywania przez przepisanie (refaktoryzację) zapytania
Oto pierwsze zadane przez Ciebie zapytanie
Spróbuj przepisać go, aby najpierw ocenić GDZIE
To zdecydowanie zmieni plan EXPLAIN. Może dawać lepsze lub gorsze wyniki.
Kiedyś odpowiedziałem na pytanie w StackOverflow, w którym zastosowałem tę technikę. EXPLAIN był przerażający, ale występ był dynamitem. Działa to tylko z powodu obecności poprawnych indeksów i zastosowania LIMIT w podzapytaniu .
Podobnie jak w przypadku cen akcji, jeśli chodzi o zapytania i próby ich wyrażenia, obowiązują ograniczenia, wyniki mogą się różnić, a wyniki w przeszłości nie wskazują przyszłych wyników.
źródło
W przypadku Oracle, ponieważ mySQL ma długi opis, mamy 2 ogólne sposoby wykorzystania optymalizatora.
Pierwszą z nich jest optymalizacja oparta na regułach (lub RBO). Oracle ma 15 wbudowanych reguł, które każde analizowane zapytanie próbuje wykonać w ustalonej kolejności. Jeśli nie będzie w stanie wygenerować zoptymalizowanego zapytania z reguły 1, przejdzie do reguły 2 i dalej, aż osiągnie regułę 15.
Aby uzyskać więcej informacji: https://docs.oracle.com/cd/B10500_01/server.920/a96533/rbo.htm
Wpływają one na jądra Oracle RDBMS od wersji 11.1 i niższych, które nie zostały przekonwertowane na Optymalizator kosztowy (inaczej CBO). Oracle 11.2 i nowsze wersje wymagają optymalizatora CBO, ale mogą zmusić określone identyfikatory Sql do optymalizacji w starej metodzie RBO, jeśli użytkownik tego chce.
CBO dla Oracle 11.1+ zamiast tego tworzy kilka planów wykonania dla tego samego identyfikatora SQL i wykonuje ten z najmniejszym ogólnie oczekiwanym kosztem. Wykorzystuje wiele logiki z RBO, ale analizuje statystyki tabeli, aby stworzyć dynamiczne koszty planu wykonania dla każdej operacji, którą DB musi zrobić, aby dostarczyć użytkownikowi końcowemu swoje dane. Wykonywanie pełnych skanów tabel na bardzo dużych stołach jest naprawdę kosztowne; wykonywanie pełnego skanowania tabeli na stole z 10 wierszami jest tanie. W RBO zostały one uznane za równe operacje.
Aby uzyskać więcej informacji: https://oracle-base.com/articles/misc/cost-based-optimizer-and-database-statistics
W przypadku konkretnego przykładu zapytania: Oracle prawdopodobnie przeanalizuje informacje w celu stworzenia różnych planów wykonania, a zatem jeden będzie lepszy technicznie od drugiego. Może to jednak być minimalna różnica. Patrząc na to, zarówno Oracle RBO, jak i CBO chcieliby zapytać o 1 więcej, ponieważ wykonuje on na sprzężeniu na mniejszych warunkach, a następnie odfiltrowuje określoną kolumnę z tabeli tymczasowej, którą utworzył ze sprzężenia.
źródło
Jeśli masz dwa zapytania i uważasz, że są one równoważne, mogą wystąpić następujące zdarzenia:
istnieją różne plany wykonania. Mamy tutaj dwie podklasy.
2.1 Zapytania mają różne plany wykonania, ale oba plany działają równie dobrze. To też jest w porządku. Nie ma potrzeby, aby dla równoważnych zapytań musiał zostać wygenerowany ten sam plan. Ale wydajność powinna być równa. I znów mamy nadzieję, że jest to najlepsze z możliwych.
2.2 Zapytania mają różne plany wykonania, a jeden plan jest lepszy od drugiego. Ponownie mamy podklasy:
2.2.1 Plany są różne, ponieważ zapytania nie są równoważne. Więc dokładnie sprawdź, czy są naprawdę równoważne. W twoim przypadku są one naprawdę równoważne.
2.2.2 Plany są różne, ale zapytania są równoważne. Oznacza to, że optymalizator nie jest wystarczająco dojrzały. W idealnym świecie z idealnymi optymalizatorami tak się nie powinno stać. Tak, to zależy od platformy i musisz przestudiować dokumenty dotyczące konkretnej platformy, aby dowiedzieć się, dlaczego tak się dzieje.
2.2.3 Plany są różne, zapytania są równoważne, oprogramowanie bazy danych ma błąd.
źródło