Operatory logiczne LUB ORAZ w stanie i porządku warunków GDZIE

33

Przeanalizujmy te dwa stwierdzenia:

IF (CONDITION 1) OR (CONDITION 2)
...

IF (CONDITION 3) AND (CONDITION 4)
...

Jeśli CONDITION 1tak TRUE, zostanie CONDITION 2sprawdzone?
Jeśli CONDITION 3tak FALSE, zostanie CONDITION 4sprawdzone?

Co z warunkami na WHERE: czy silnik SQL Server optymalizuje wszystkie warunki w WHEREklauzuli? Czy programiści powinni umieszczać warunki we właściwej kolejności, aby mieć pewność, że optymalizator SQL Server rozwiąże je we właściwy sposób?

DODANY:

Dziękuję Jackowi za link, niespodzianka z kodu t-sql:

IF  1/0 = 1 OR 1 = 1
      SELECT 'True' AS result
ELSE
      SELECT 'False' AS result


IF  1/0 = 1 AND 1 = 0
      SELECT 'True' AS result
ELSE
      SELECT 'False' AS result

W tym przypadku nie występuje wyjątek dzielenia przez zero .

WNIOSEK:

Jeśli w C ++ / C # / VB występuje zwarcie, dlaczego SQL Server go nie ma?

Aby naprawdę na to odpowiedzieć, rzućmy okiem na to, jak oboje pracują w warunkach. Wszystkie C ++ / C # / VB mają zwarcie zdefiniowane w specyfikacjach języka, aby przyspieszyć wykonanie kodu. Po co zawracać sobie głowę oceną N warunków, gdy pierwszy jest już prawdziwy, lub M AND warunków, gdy pierwszy jest już fałszywy.

Jako programiści musimy pamiętać, że SQL Server działa inaczej. Jest to system oparty na kosztach. Aby uzyskać optymalny plan wykonania dla naszego zapytania, procesor zapytań musi ocenić każdy warunek i przypisać mu koszt. Koszty te są następnie oceniane jako całość, aby utworzyć próg, który musi być niższy niż zdefiniowany próg, który SQL Server ma dla dobrego planu. Jeśli koszt jest niższy niż zdefiniowany próg, stosowany jest plan, jeśli nie, cały proces powtarza się ponownie z inną kombinacją kosztów warunkowych. Koszt tutaj to albo skanowanie, albo wyszukiwanie, łączenie scalające, łączenie mieszające itp. Z tego powodu zwarcie, jak to jest dostępne w C ++ / C # / VB, po prostu nie jest możliwe. Możesz pomyśleć, że wymuszenie użycia indeksu na kolumnie liczy się jako zwarcie, ale tak nie jest. Wymusza to jedynie użycie tego indeksu, a tym samym skraca listę możliwych planów wykonania. System nadal opiera się na kosztach.

Jako programista musisz mieć świadomość, że SQL Server nie powoduje zwarć, jak ma to miejsce w innych językach programowania i nie możesz nic zrobić, aby zmusić go do tego.

garik
źródło
Skąd pochodzi ostatni blok wyceny? Czy możesz dodać referencję?
Nick Chammas,

Odpowiedzi:

25

W SQL Server nie ma gwarancji, czy lub w jakiej kolejności instrukcje będą przetwarzane w WHEREklauzuli. Pojedyncze wyrażenie, które pozwala na zwarcie instrukcji, to CASE- WHEN. Poniżej znajduje się odpowiedź, którą opublikowałem na Stackoverflow:

Jak SQL Server zwiera GDZIE ocena stanu

Dzieje się tak, kiedy ma się na to ochotę, ale nie w taki sposób, w jaki od razu myślisz.

Jako programista musisz mieć świadomość, że SQL Server nie powoduje zwarć, jak ma to miejsce w innych językach programowania i nie możesz nic zrobić, aby zmusić go do tego .

Aby uzyskać więcej informacji, sprawdź pierwszy link w powyższym wpisie na blogu, który prowadzi do innego bloga:

Czy w SQL Server występuje zwarcie?

Ostateczny werdykt? Cóż, tak naprawdę nie mam jeszcze takiego, ale prawdopodobnie bezpiecznie jest powiedzieć, że jedynym czasem, w którym można zapewnić określone zwarcie, jest wyrażanie wielu warunków KIEDY w wyrażeniu CASE. W przypadku standardowych wyrażeń boolowskich optymalizator przesunie się według własnego uznania w oparciu o tabele, indeksy i dane, o które pytasz.

MicSim
źródło
2
Najwyraźniej istnieją pewne przypadki krawędzi (lub błąd), w których nawet case nie jest bezpieczny
Jack Douglas
1
Pokazuję też inny przypadek (ha!), W którym CASEprzerwy: dba.stackexchange.com/questions/12941/…
Aaron Bertrand
0

SQL jest deklaratywnym językiem programowania. W przeciwieństwie do powiedzmy C ++, który jest imperatywnym językiem programowania.

Oznacza to, że możesz powiedzieć, co chcesz w wyniku końcowym, ale nie możesz dyktować, w jaki sposób wynik jest wykonywany, wszystko zależy od silnika.

Jedynym prawdziwym sposobem zagwarantowania „zwarcia” (lub dowolnego innego przepływu sterowania ) w środku WHEREjest użycie widoków indeksowanych, tabel tymczasowych i podobnych mechanizmów.

PS. Możesz także użyć wskazówek dotyczących planu wykonania (aby „podpowiedzieć” silnikowi, jak wykonać zapytanie, które indeksy użyć i JAK ich używać), pomyślałem, że powinienem o tym wspomnieć, skoro jesteśmy na ten temat ...

jitbit
źródło
-4

1) - LUB (jeden lub oba warunki będą PRAWDA)

jeśli warunek 1 ma wartość PRAWDA, wówczas warunek 2 również sprawdzi, czy może to być PRAWDA lub FAŁSZ

--AND (oba warunki muszą być PRAWDĄ)

jeśli warunek 1 ma wartość FAŁSZ, warunek 2 nie zostanie sprawdzony

Ranjith Kumar
źródło
„jeśli warunek 1 ma wartość FAŁSZ, wówczas warunek 2 nie zostanie sprawdzony” To nie jest prawda. Zobacz odpowiedź powyżej . SQL Server może nadal oceniać warunek 2, ponieważ nie wykonuje oceny zwarcia w WHEREklauzulach.
Nick Chammas
-4

Jedynym sposobem kontrolowania, w jaki sposób warunki w klauzuli WHERE, jest użycie nawiasów, aby je zgrupować.

WHERE Col1 = 'Something' AND Col2 = 'Something' OR Col3 = 'Something' and Col4 = 'Something'

jest bardzo różny od

WHERE (Col1 = 'Something' AND Col2 = 'Something') OR (Col3 = 'Something' and Col4 = 'Something')
mrdenny
źródło
Po prostu ciekawy. Czym różnią się te dwa warunki? Różne wyniki, wydajność, plan wykonania? Myślałem, że będą równoważne.
ypercubeᵀᴹ
W pierwszym przypadku musisz dopasować Col1, Col4 i Col2 lub Col3. W drugim wierszu, aby dopasować Col1 i Col2, lub musisz dopasować Col3 i Col4, ale Col1 i Col4 nigdy nie będą musiały być oceniane razem.
mrdenny
1
Nie, mylisz się. ANDma wyższy priorytet niż OR. Oba są równoważne. To, co powiesz, będzie prawdziwe dla WHERE Col1 = x AND (Col2 = x OR Col3 = x) AND Col4 = xzapytania. Zobacz test Fiddle SQL
ypercubeᵀᴹ