Warunek w ramach DOŁĄCZ lub GDZIE


194

Czy jest jakaś różnica (wydajność, najlepsza praktyka itp.) Między umieszczeniem warunku w klauzuli JOIN a klauzuli WHERE?

Na przykład...

-- Condition in JOIN
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
AND CUS.FirstName = 'John'

-- Condition in WHERE
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID
WHERE CUS.FirstName = 'John'

Który wolisz (a może dlaczego)?


4
Czy uruchomiłeś dwa zapytania? Czy sprawdziłeś plany wykonania wygenerowane przez dwa zapytania? Co zaobserwowałeś
S.Lott,

22
@ S.Lott, to zapytanie służy wyłącznie do celów. Zastanawiam się tylko „ogólnie”, która metoda jest preferowana - jeśli w ogóle.
Steve Dignan,

1
@ Steve Dignan: Powinieneś porównać to z przykładowymi danymi i spojrzeć na plany zapytań. Odpowiedź będzie bardzo, bardzo jasna. I - bonus - będziesz miał kod, którego możesz użyć ponownie, gdy pojawią się bardziej złożone sytuacje.
S.Lott,

1
Osobiście umieściłbym warunek w klauzuli JOIN, jeśli warunek opisuje relację. Ogólne warunki, które po prostu filtrują zestaw wyników, przejdą do GDZIE. Np.FROM Orders JOIN OrderParties ON Orders.Id = OrderParties.Order AND OrderParties.Type = 'Recipient' WHERE Orders.Status = 'Canceled'
Glutexo

Odpowiedzi:


154

Algebra relacyjna umożliwia zamienność predykatów w WHEREklauzuli i INNER JOIN, więc nawet INNER JOINzapytania z WHEREklauzulami mogą przestawiać predykaty przez optymalizator, aby mogły zostać już wykluczone podczas JOINprocesu.

Polecam pisanie zapytań w możliwie najbardziej czytelny sposób.

Czasami obejmuje to uczynienie INNER JOINwzględnie „niekompletnym” i umieszczenie niektórych kryteriów w WHEREcelu ułatwienia zarządzania listami kryteriów filtrowania.

Na przykład zamiast:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
    AND c.State = 'NY'
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
    AND a.Status = 1

Pisać:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
    AND a.Status = 1

Ale to oczywiście zależy.


7
Nie chodzi tylko o czyste zapytanie lub czytelność, ale o wydajność. łączenie warunków poprawia wydajność dla dużej ilości danych dzięki odpowiednio indeksowanym tabelom.
Shahdat,

1
Właśnie uruchamiam miesięczne raporty sprzedaży łączące 5-6 tabel na kilku milionach rekordów. Perf poprawia się o 30% - serwer sql 2012
Shahdat

2
@Shahdat, jeśli zauważasz znaczącą różnicę w wydajności, przenosząc warunki filtru z klauzuli where na połączenie wewnętrzne, musisz opublikować te plany wykonania.
Cade Roux,

4
@Cade Zbadałem plany wykonania - oba scenariusze wykazują ten sam koszt. Uruchamiam zapytania wiele razy, wydaje się, że oba zajmują tyle samo czasu. Wcześniej uruchamiałem zapytania dotyczące produkcji i miałem znaczną różnicę wydajności, ponieważ baza danych była używana przez użytkowników na żywo. Przepraszam za zamieszanie.
Shahdat,

4
Ta odpowiedź jest odpowiednia dla ŁĄCZENIA WEWNĘTRZNEGO, ale nie dotyczy złączeń lewy / prawy.
sotn
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.