Czy wyrażenia boolowskie w klauzulach SQL WHERE są oceniane jako zwarte ?
Na przykład:
SELECT *
FROM Table t
WHERE @key IS NULL OR (@key IS NOT NULL AND @key = t.Key)
Jeśli @key jest NULL wartość true, to @key IS NOT NULL AND @key = t.Key oceniane?
Jeśli nie, dlaczego nie?
Jeśli tak, czy jest to gwarantowane? Czy jest to część ANSI SQL, czy jest to specyficzne dla bazy danych?
Jeśli specyficzna dla bazy danych, SqlServer? Wyrocznia? MySQL?
sql
short-circuiting
Greg Dean
źródło
źródło
WHERE a = 1 AND b = 2
może być wydajne, aby silnik bazy danych znalazł najpierw wszystkie wiersze, w których b = 2, a następnie filtruj, gdzie a = 1. Jeśli poprosisz o gwarancję, optymalizator stanie się bezużyteczny.Odpowiedzi:
ANSI SQL Draft 2003 5WD-01-Framework-2003-09.pdf
źródło
CASE
jest zwarty.Z powyższego wynika, że zwarcie nie jest naprawdę dostępne.
Jeśli potrzebujesz, proponuję oświadczenie Case:
Expr1
jest zawsze oceniana, ale tylko jedna z nichExpr2
iExpr3
będzie oceniana na wiersz.źródło
Myślę, że to jeden z przypadków, w których napisałbym to tak, jakby nie powodowało zwarcia, z trzech powodów.
Ponieważ w przypadku MSSQL nie można go rozwiązać, patrząc na BOL w oczywistym miejscu, więc dla mnie jest to kanonicznie niejednoznaczne.
bo przynajmniej wtedy wiem, że mój kod będzie działał. A co ważniejsze, tak samo będzie z tymi, którzy przyjdą po mnie, więc nie będę ich zmuszać do martwienia się w kółko o to samo pytanie.
Piszę wystarczająco często dla kilku produktów DBMS i nie chcę pamiętać różnic, jeśli mogę je łatwo obejść.
źródło
Nie wierzę, że zwarcie w SQL Server (2005) jest gwarantowane. SQL Server przeprowadza zapytanie poprzez algorytm optymalizacji, który bierze pod uwagę wiele czynników (indeksy, statystyki, rozmiar tabeli, zasoby itp.), Aby opracować efektywny plan wykonania. Po tej ocenie nie można z całą pewnością stwierdzić, że logika zwarcia jest gwarantowana.
Sam kiedyś napotkałem to samo pytanie i moje badania naprawdę nie dały mi ostatecznej odpowiedzi. Możesz napisać małe zapytanie, aby dać ci poczucie, że to działa, ale czy możesz być pewien, że wraz ze wzrostem obciążenia bazy danych, tabele stają się większe, a rzeczy są optymalizowane i zmieniane w bazie danych, ten wniosek będzie utrzymać. Nie mogłem i dlatego popełniłem błąd po stronie ostrożności i użyłem CASE w klauzuli WHERE, aby zapewnić zwarcie.
źródło
Musisz pamiętać, jak działają bazy danych. Biorąc pod uwagę sparametryzowane zapytanie, db buduje plan wykonania w oparciu o to zapytanie bez wartości parametrów. To zapytanie jest używane za każdym razem, gdy zapytanie jest uruchamiane, niezależnie od rzeczywistych podanych wartości. Plan wykonania nie ma znaczenia, czy w zapytaniu występują zwarcia z określonymi wartościami.
źródło
Zwykle używam tego dla parametrów opcjonalnych. Czy to to samo, co zwarcie?
Daje mi to opcję przekazania -1 lub czegokolwiek, aby uwzględnić opcjonalne sprawdzenie atrybutu. Czasami wiąże się to z łączeniem się na wielu stołach lub najlepiej w widoku.
Bardzo poręczny, nie do końca pewny dodatkowej pracy jaką daje silnik db.
źródło
Myślę, że w przypadku SQL Server zależy to od wersji, ale moje doświadczenie z SQL Server 2000 polega na tym, że nadal ocenia on @key = t.Key, nawet jeśli @key ma wartość null. Innymi słowy, nie powoduje efektywnego zwarcia podczas oceny klauzuli WHERE.
Widziałem ludzi zalecających strukturę, taką jak twój przykład, jako sposób na wykonanie elastycznego zapytania, w którym użytkownik może wprowadzić lub nie wprowadzić różne kryteria. Moją obserwacją jest to, że Key jest nadal zaangażowany w plan kwerend, gdy @key ma wartość null, a jeśli klucz jest indeksowany, nie używa go wydajnie.
Ten rodzaj elastycznych zapytań z różnymi kryteriami jest prawdopodobnie jednym z przypadków, w których dynamicznie utworzony SQL jest naprawdę najlepszym rozwiązaniem. Jeśli @key ma wartość null, po prostu w ogóle go nie uwzględniasz w zapytaniu.
źródło
Właśnie natknąłem się na to pytanie i już znalazłem ten wpis na blogu: http://rusanu.com/2009/09/13/on-sql-server-boolean-operator-short-circuit/
Serwer SQL może optymalizować zapytanie w dowolnym miejscu, które uzna za stosowne, więc w przykładzie podanym w poście na blogu nie można polegać na zwarciu.
Jednak CASE jest najwyraźniej udokumentowany w celu oceny w kolejności pisemnej - sprawdź komentarze do tego posta na blogu.
źródło
Główną cechą oceny zwarcia jest to, że przestaje ona oceniać wyrażenie, gdy tylko można określić wynik. Oznacza to, że resztę wyrażenia można zignorować, ponieważ wynik będzie taki sam, niezależnie od tego, czy jest oceniany, czy nie.
Binarne operatory logiczne są przemienne, co oznacza:
więc nie ma gwarancji kolejności oceny. Kolejność oceny zostanie określona przez optymalizator zapytań.
W językach z obiektami mogą wystąpić sytuacje, w których można napisać wyrażenia logiczne, które można ocenić tylko za pomocą oceny zwarcia. Twoja przykładowa konstrukcja kodu jest często używana w takich językach (C #, Delphi, VB). Na przykład:
Ten przykład C # spowoduje wyjątek, jeśli
someString == null
ponieważ zostanie w pełni oceniony. W ocenie zwarć będzie działać za każdym razem.SQL działa tylko na zmiennych skalarnych (bez obiektów), których nie można odinicjalizować, więc nie ma możliwości napisania wyrażenia boolowskiego, którego nie można ocenić. Jeśli masz jakąś wartość NULL, każde porównanie zwróci fałsz.
Oznacza to, że w SQL nie można napisać wyrażenia, które jest inaczej oceniane w zależności od zastosowania zwarcia lub pełnej oceny.
Jeśli implementacja SQL wykorzystuje ocenę zwarć, może tylko przyspieszyć wykonanie zapytania.
źródło
nie wiem o krótkim krążeniu, ale zapisałbym to jako stwierdzenie if-else
również zmienne powinny zawsze znajdować się po prawej stronie równania. to czyni go możliwym do rozstrzygnięcia.
http://en.wikipedia.org/wiki/Sargable
źródło
Poniżej szybki i brudny test na SQL Server 2008 R2:
Wraca natychmiast bez żadnych rekordów. Wystąpił rodzaj zachowania zwarciowego.
Następnie spróbowałem tego:
wiedząc, że żaden rekord nie spełnia tego warunku:
Zajęło to kilka sekund, wskazując, że zachowanie zwarcia już nie występowało i złożona operacja była oceniana dla każdego rekordu.
Mam nadzieję, że to pomaga ludziom.
źródło
Oto demo, które ma udowodnić, że MySQL wykonuje skracanie klauzuli WHERE :
http://rextester.com/GVE4880
Spowoduje to uruchomienie następujących zapytań:
Jedyną różnicą między nimi jest kolejność operandów w warunku OR.
myslowfunction
celowo zasypia na sekundę i ma efekt uboczny polegający na dodawaniu wpisu do tablicy dziennika przy każdym uruchomieniu. Oto wyniki tego, co jest rejestrowane podczas uruchamiania dwóch powyższych zapytań:Powyższe pokazuje, że powolna funkcja jest wykonywana więcej razy, gdy pojawia się po lewej stronie warunku LUB, gdy drugi operand nie zawsze jest prawdziwy (z powodu zwarcia).
źródło
Zajmuje to dodatkowe 4 sekundy w analizatorze zapytań, więc z tego, co widzę, nie jest nawet zwarte ...
Byłoby miło mieć gwarantowany sposób!
źródło
Jest jednak oczywiste, że serwer MS Sql obsługuje teorię zwarć, aby poprawić wydajność, unikając niepotrzebnego sprawdzania,
Wspierający przykład:
W tym przypadku pierwszy przykład spowodowałby błąd „Konwersja nie powiodła się podczas konwersji wartości varchar„ A ”na typ danych int.”
Podczas gdy drugi działa łatwo, ponieważ warunek 1 = 1 jest oceniany na PRAWDA, a zatem drugi warunek w ogóle nie działa.
Ponadto
tutaj pierwszy warunek zostanie uznany za fałszywy i dlatego DBMS przejdzie do drugiego warunku i ponownie otrzymasz błąd konwersji, jak w powyższym przykładzie.
UWAGA: NAPISŁEM BŁĘDNY WARUNEK TYLKO, ABY ZREALIZOWAĆ POGODĘ STAN JEST WYKONANY LUB ZWARCIE, JEŚLI ZAPYTANIE WYNIKA BŁĄD OZNACZA STAN WYKONANY, ZWARCIOWY W INNY SPOSÓB.
PROSTE WYJAŚNIENIE
Rozważać,
ponieważ pierwszy warunek jest oceniany jako PRAWDA , nie ma sensu oceniać drugiego warunku, ponieważ jego ocena w jakiejkolwiek wartości nie wpłynęłaby w ogóle na wynik, więc jest to dobra okazja dla Sql Server, aby zaoszczędzić czas wykonania zapytania, pomijając niepotrzebne sprawdzanie lub ocenę warunków .
w przypadku „LUB”, jeśli pierwszy warunek ma wartość PRAWDA, cały łańcuch połączony przez „LUB” zostałby uznany za oceniony jako prawdziwy bez oceny innych.
jeśli warunek warunek1 zostanie oszacowany jako prawdziwy, wszystkie warunki spocznij, aż warunekN zostanie pominięty. W uogólnionych słowach przy określaniu pierwszego PRAWDA wszystkie inne warunki połączone przez OR zostaną pominięte.
Rozważ drugi warunek
ponieważ pierwszy warunek jest oceniany na FAŁSZ oceniany nie ma sensu oceniać drugiego warunku, ponieważ jego ocena w jakiejkolwiek wartości nie wpłynęłaby w ogóle na wynik, więc ponownie jest to dobra okazja dla Sql Server, aby zaoszczędzić czas wykonania zapytania, pomijając niepotrzebne sprawdzanie lub ocenę stanu .
w przypadku „AND”, jeśli pierwszy warunek ma wartość FALSE, cały łańcuch połączony z „AND” zostałby uznany za oszacowany na FALSE bez oceny innych.
jeśli condition1 oceniana jest na FAŁSZ , reszta wszystkie warunki till conditionN będzie pominięty. W uogólnionych słowach przy określaniu pierwszego FAŁSZ , wszystkie inne warunki połączone operatorem AND zostaną pominięte.
Dlatego mądry programista powinien zawsze programować łańcuch warunków w taki sposób, aby mniej kosztowny lub najbardziej eliminujący warunek był oceniany w pierwszej kolejności, lub tak ustalał stan w taki sposób, który przynosiłby maksymalne korzyści
źródło