Dobry, zły lub obojętny: GDZIE 1 = 1

14

Biorąc pod uwagę to pytanie na reddit, wyczyściłem zapytanie, aby wskazać, gdzie problem był w zapytaniu. Najpierw używam przecinka, WHERE 1=1aby ułatwić modyfikowanie zapytań, więc moje zapytania zwykle kończą się tak:

SELECT 
     C.CompanyName
    ,O.ShippedDate
    ,OD.UnitPrice
    ,P.ProductName
FROM 
               Customers       as C
    INNER JOIN Orders          as O  ON C.CustomerID = O.CustomerID
    INNER JOIN [Order Details] as OD ON O.OrderID    = OD.OrderID
    INNER JOIN Products        as P  ON P.ProductID  = OD.ProductID
Where 1=1
--  AND O.ShippedDate Between '4/1/2008' And '4/30/2008'
    And P.productname = 'TOFU'
Order By C.CompanyName

Ktoś w zasadzie powiedział, że 1 = 1 jest ogólnie leniwy i źle wpływa na wydajność .

Biorąc pod uwagę, że nie chcę „przedwcześnie optymalizować” - chcę przestrzegać dobrych praktyk. Wcześniej przeglądałem plany zapytań, ale ogólnie tylko po to, aby dowiedzieć się, jakie indeksy mogę dodać (lub dostosować), aby moje zapytania działały szybciej.

Pytanie naprawdę ... czy Where 1=1powoduje złe rzeczy? A jeśli tak, jak mogę to stwierdzić?

Drobna edycja: Zawsze też „zakładałem”, 1=1że zostanie zoptymalizowany, aw najgorszym razie będzie nieistotny. Nigdy nie boli kwestionować mantry, takiej jak „Goto's Evil” lub „Premature Optimization ...” lub inne domniemane fakty. Nie byłem pewien, czy 1=1 ANDrealistycznie wpłynie to na plany zapytań, czy nie. A co z podkwerendami? CTE? Procedury?

Nie jestem osobą do optymalizacji, chyba że jest to potrzebne ... ale jeśli robię coś, co w rzeczywistości jest „złe”, chciałbym zminimalizować efekty lub zmienić w stosownych przypadkach.

WernerCD
źródło
2
Nie zrobiłby tego. Oprócz kilku mikrosekund dla optymalizatora, aby usunąć zbędny warunek. Lepiej skup się na literalnych datach, które nie są dwuznaczne.
ypercubeᵀᴹ
Jak powiedział @ypercube, nie ma to znaczenia. Optymalizator zapytań musiałby być kawałkiem ****, aby coś takiego miało jakąkolwiek różnicę;)
Philᵀᴹ
4
Nie wierz we wszystko, co czytasz na reddit. Proszę.
Aaron Bertrand
1
@AaronBertrand Biorę wszystko z odrobiną soli, dopóki nie doświadczyłem tego z pierwszej ręki. Nadal odpowiem na pytanie, które wydaje się wiarygodne, i sprawdzę, czy jest w tym jakaś prawda, zwłaszcza jeśli ma to wpływ na moją codzienną pracę.
WernerCD
4
Są ziarna soli, a następnie zawartość soli całego oceanu zrzucona na szczyt biurowca: P
Philᵀᴹ

Odpowiedzi:

13

SQL Server parserOptymalizator ma funkcję o nazwie „Stałe składanie”, która eliminuje wyrażenia tautologiczne z zapytania.
Jeśli spojrzysz na plan wykonania, nigdzie w predykatach nie zobaczysz tego wyrażenia. Oznacza to, że stałe składanie i tak jest wykonywane w czasie kompilacji z tego i innych powodów i nie ma wpływu na wydajność zapytań.

Aby uzyskać więcej informacji, zobacz Ciągłe składanie i ocena wyrażeń podczas szacowania liczności .

spaghettidba
źródło
Prawdopodobnie jest skompilowany, ponieważ jest to znany wzorzec łączenia danych między polami.
jcolebrand
Nie, jest kompilowany, ponieważ jest tautologiczny. Działałoby to w ten sam sposób z 2736 = 2736, co nie jest tak zwyczajne jak 1 = 1. To samo dotyczy sprzeczności. W takim przypadku funkcja nosi nazwę „Wykrywanie sprzeczności”.
spaghettidba
Która część „znanego wzoru” oznaczała „musi być 1 = 1”?
jcolebrand
9

Dodanie nadmiarowego predykatu może mieć znaczenie w SQL Server.

W poniższych planach wykonania zwróć uwagę @1na pierwszy plan vs. literał 'foo'w drugim planie.

wprowadź opis zdjęcia tutaj

Oznacza to, że SQL Server wziął pod uwagę pierwsze zapytanie w celu prostej parametryzacji celu promowania ponownego użycia planu wykonania - jednak porównanie dwóch stałych zapobiega temu w drugim przypadku.

Lista warunków, które uniemożliwiają prostą parametryzację (wcześniej znaną jako autoparametryzacja) można znaleźć w załączniku A do dokumentacji technicznej Microsoft Caching Plan:

prosta parametryzacja nie jest jednak czymś, na czym powinieneś polegać. Zdecydowanie lepiej jest sparametryzować swoje zapytania.

Martin Smith
źródło
4

W każdym nowoczesnym RDBMS (w tym Oracle, Microsoft SQL Server i PostgreSQL - jestem tego pewien) nie będzie to miało wpływu na wydajność.

Jak ktoś zauważył, będzie to miało wpływ tylko na fazę planowania zapytań. Dlatego różnica będzie widoczna tylko wtedy, gdy uruchomisz tysiące iteracji uproszczonego zapytania, które nie zwraca żadnych danych, takich jak ten:

SELECT 1 FROM empty_table; -- run this 10 000 times.

SELECT 1 FROM empty_table WHERE 1=1; -- run this 10 000 times and compare.

Dla mnie w PostgreSQL 9.0 jest to widoczne tylko przy 10000 iteracjach:

filip@srv:~$ pgquerybench.pl -h /var/run/postgresql/ -q "select 1 from never where 1=1" -q "select 1 from never" -i 10000
Iterations: 10000
Query:   select 1 from never where 1=1
Total:   2.952 s
Average: 0.295 ms
Query:   select 1 from never
Total:   2.850 s
Average: 0.285 ms
filiprem
źródło
0

Może to stanowić „problem” dla Oracle, gdy używasz parametru bazy danych sharing_sharing. Ustawienie tej opcji na „wymuś” spowoduje zmodyfikowanie wszystkich instrukcji SQL. Wszystkie „stałe” w zapytaniach zostaną zastąpione zmiennymi powiązania (np. 1 =>: SYS_0).

Ta opcja została wprowadzona, aby poradzić sobie z niektórymi leniwymi programistami. Z drugiej strony może też zaszkodzić innym leniwym programistom. Ale ryzyko nie jest zbyt wysokie. Od 11g ma funkcję podglądu zmiennych.

ibre5041
źródło
Czy możesz wyjaśnić, co: „Od 11g ma funkcję podglądania zmiennych.” znaczy?
ypercubeᵀᴹ
@ypercube „Podgląd zmiennych powiązań” oznacza, że ​​optymalizator będzie obserwował rzeczywiste wartości zmiennych powiązań i użyje statystyk danych do ponownej oceny i ewentualnie ponownego wygenerowania planu wykonania zapytania. Wątpię, by podglądanie miało jakikolwiek wpływ na omawiany konstrukt, ponieważ nie zależy od statystyki danych.
mustaccio