Czy kolejność klauzul ma znaczenie w SQL?

121

Powiedzmy, że mam tabelę PEOPLEo nazwie mająca 3 kolumny ID, LastName, FirstName, żadna z tych kolumn nie jest indeksowana.
LastNamejest bardziej wyjątkowy i FirstNamemniej wyjątkowy.

Jeśli przeprowadzę 2 wyszukiwania:

select * from PEOPLE where FirstName="F" and LastName="L" 
select * from PEOPLE where LastName="L" and FirstName="F"

Uważam, że to drugie jest szybsze, ponieważ bardziej unikalne kryterium ( LastName) znajduje się na pierwszym miejscu w whereklauzuli, a rekordy będą eliminowane skuteczniej. Nie sądzę, aby optymalizator był wystarczająco inteligentny, aby zoptymalizować pierwszy plik sql.

Czy moje rozumienie jest prawidłowe?

Ziyang Zhang
źródło
8
Nie, ta kolejność nie ma znaczenia - każdy przyzwoity optymalizator zapytań przejrzy wszystkie klauzule WHERE i znajdzie najbardziej efektywny sposób spełnienia tego zapytania
marc_s
3
Jakie były twoje spostrzeżenia, kiedy przeprowadzałeś te dwa oświadczenia? Jak wyglądały plany egzekucyjne?
Conrad Frix
3
Czy odnosisz się do konkretnego RDBMS? Rzeczywiście istnieją różnice.
Bjoern,

Odpowiedzi:

101

Nie, ta kolejność nie ma znaczenia (a przynajmniej: nie powinna mieć znaczenia).

Każdy przyzwoity optymalizator zapytań przeanalizuje wszystkie części WHEREklauzuli i znajdzie najbardziej efektywny sposób spełnienia tego zapytania.

Wiem, że optymalizator zapytań SQL Server wybierze odpowiedni indeks - bez względu na to, w jakiej kolejności masz dwa warunki. Zakładam, że inne RDBMS będą miały podobne strategie.

Liczy się to, czy masz do tego odpowiedni indeks!

W przypadku SQL Server najprawdopodobniej użyje indeksu, jeśli masz:

  • indeks na (LastName, FirstName)
  • indeks na (FirstName, LastName)
  • indeks tylko (LastName)lub tylko (FirstName)(lub obu)

Z drugiej strony - znowu dla SQL Server - jeśli użyjesz SELECT *do pobrania wszystkich kolumn z tabeli, a tabela jest raczej mała, istnieje duża szansa, że ​​optymalizator zapytań po prostu wykona skanowanie tabeli (lub indeksu klastrowego) zamiast używać indeks (ponieważ wyszukiwanie na pełnej stronie danych w celu uzyskania wszystkich innych kolumn staje się zbyt drogie, bardzo szybko).

marc_s
źródło
Jeśli nie ma indeksów, op może być poprawny, w zależności od danych. Oczywiście zrobienie czegoś takiego bez indeksów byłoby dziwną decyzją ...
Tony Hopkinson.
@TonyHopkinson: Nie sądzę - nawet bez indeksów wątpię, czy jest jakaś różnica. W końcu: bez indeksów, co innego oprócz pełnego skanowania tabeli może zrobić RDBMS, naprawdę?
marc_s
2
Interesująca uwaga dodatkowa dotycząca serwera SQL, najwyraźniej kolejność NIE ISTNIEJE w predykatach może faktycznie wpłynąć na tworzenie planu: bradsruminations.blogspot.com/2010/04/looking-under-hood.html
Justin Swartsel
3
Dziwne jest to, że przy pierwszym wykonaniu zapytania kolejność warunków w klauzuli WHERE DOES MATER MATER! Miałem dwa warunki, coś w stylu: WHERE T1.col_1/T2.col_2 > 10 AND T2.col_2 <> 0i wyskoczył DIVIDE BY 0błąd. Po zmianie kolejności warunków zapytanie zostało wykonane pomyślnie. Potem zmieniłem zlecenie z powrotem, więc spodziewałem się, że znowu wystąpi błąd, ale tym razem zadziałało! W końcu doszedłem do wniosku, że dla pierwszego przebiegu zlecenie ma znaczenie, dopóki nie zostanie zbudowany plan wykonania. 't ma znaczenie', ponieważ optymalizator / plan wykonawczy zajmie się tym
Radu Gheorghiu
1
Podoba mi się, że powiedziałeś: „... a przynajmniej nie powinno mieć znaczenia” - całkowicie się zgadzam. Niestety, czasami ma to znaczenie. Widziałem przypadki, w których SQL był zbyt złożony, aby optymalizator mógł obsłużyć i rzeczy takie jak kolejność kolumn i kolejność łączenia tabel robiły różnicę. Zależy to od RDBMS, złożoności instrukcji SQL, a nawet wersji. Bardzo złożony kod SQL może powodować złe decyzje optymalizatora lub użycie zakodowanych na stałe wartości domyślnych w kodzie optymalizatora.
Victor Di Leo,
19

Kolejność klauzul WHERE nie powinna mieć wpływu na bazę danych zgodną ze standardem SQL. W większości baz danych kolejność ocen nie jest gwarantowana.

Nie myśl, że SQL dba o kolejność. Poniższe generuje błąd w programie SQL Server:

select *
from INFORMATION_SCHEMA.TABLES
where ISNUMERIC(table_name) = 1 and CAST(table_name as int) <> 0

Gdyby pierwsza część tej klauzuli została wykonana jako pierwsza, wówczas tylko numeryczne nazwy tabel byłyby rzutowane jako liczby całkowite. Jednak kończy się to niepowodzeniem, dając jasny przykład, że SQL Server (podobnie jak w przypadku innych baz danych) nie dba o kolejność klauzul w instrukcji WHERE.

Gordon Linoff
źródło
Co ma wspólnego to zapytanie powodujące błąd z kolejnością oceny predykatu GDZIE?
Jim,
7
@Jim If ISNUMERIC(table_name) = 1został obliczony jako pierwszy, a następnie CASTzostanie wywołany tylko w przypadku nazw tabel numerycznych. Ale ponieważ nie jest on oceniany jako pierwszy, CASTjest również oceniany pod kątem nienumerycznych nazw tabel, powodując komunikat o błędzie.
hibbelig
2
Doskonałe wyjaśnienie
neeohw
Dla pewności sprawdziłem, czy zamiana warunków spowodowałaby, że serwer SQL obsłużyłby je na odwrót, ale zawodzi to w obie strony. Myślę, że może to oznaczać jedną z dwóch rzeczy: (1) nie optymalizuje tak dobrze, jak mogłoby lub (2) jest to błąd kompilacji, a SQL nawet nie próbuje niczego porównywać, eliminując wstępne koszty. Domyślam się, że to nr. 2.
Louis Somers,
9

ANSI SQL Draft 2003 5WD-01-Framework-2003-09.pdf

6.3.3.3 Kolejność oceny reguł

...

Tam, gdzie pierwszeństwo nie jest określone przez formaty lub nawiasy, efektywna ocena wyrażeń jest zwykle wykonywana od lewej do prawej. Jednak od implementacji zależy, czy wyrażenia są faktycznie oceniane od lewej do prawej, szczególnie gdy operandy lub operatory mogą powodować podniesienie warunków lub jeśli wyniki wyrażeń można określić bez całkowitego oceniania wszystkich części wyrażenia.

skopiowane stąd

03Usr
źródło
2

Nie, wszystkie RDBM najpierw zaczynają się od analizy zapytania i optymalizują je przez zmianę kolejności klauzuli where.

W zależności od tego, którego RDBM używasz, możesz wyświetlić wynik analizy (na przykład wyszukaj plan wyjaśnienia w Oracle)

M.

poussma
źródło
Robi to na podstawie indeksów. Więc jest to pośrednie pod względem treści.
Tony Hopkinson,
1

Oryginalne oświadczenie OP

Uważam, że to drugie jest szybsze, ponieważ bardziej unikalne kryterium (LastName) znajduje się na pierwszym miejscu w klauzuli Where, a rekordy zostaną efektywniej wyeliminowane. Nie sądzę, aby optymalizator był wystarczająco inteligentny, aby zoptymalizować pierwszy plik sql.

Myślę, że mylisz to z wyborem kolejności kolumn podczas tworzenia indeksów, w których najpierw musisz umieścić bardziej selektywne kolumny niż drugie najbardziej selektywne i tak dalej.

BTW, dla powyższych dwóch zapytań optymalizator serwera SQL nie dokona żadnej optymalizacji, ale użyje planu Trivila, o ile całkowity koszt planu jest mniejszy niż koszt progowy równoległości.

Gulli Meel
źródło
0

To prawda, zakładając, że nazwiska nie są indeksowane. Jednak inne dane mogą być błędne. Aby dowiedzieć się, w jaki sposób to zrobić, który może się różnić za każdym razem, DBMS musiałby uruchomić odrębne zapytanie zliczające dla każdej kolumny i porównać liczby, co kosztowałoby więcej niż zwykłe wzruszanie ramionami i kontynuowanie.

Tony Hopkinson
źródło