2010-10-09 23 views
10

Słyszałem, że powinny być preferowane połączenia zamiast zagnieżdżonych zapytań. Czy to prawda w ogóle? Lub mogą istnieć scenariusze, w których jeden byłby szybszy od innych:Zagnieżdżona kwerenda lub łączy

np. który jest bardziej wydajny sposób napisać kwerendę ?:

Select emp.salary 
from employee emp  
where emp.id = (select s.id from sap s where s.id = 111) 

LUB

Select emp.salary  
from employee emp 
INNER JOIN sap s ON emp.id = s.id 
WHERE s.id = 111 
+0

A co z tym, że warunek miejsca jest częścią warunku łączenia? INNER JOIN sap s na emp.id = s.id i s.id = 111 – Tim

Odpowiedz

9

Słyszałem, że połączenia powinny być preferowane w stosunku do zagnieżdżonych zapytań. Czy to prawda w ogóle?

To zależy od wymagań i danych.

Używanie JOIN ryzykuje powielenie informacji w zestawie wyników dla tabeli nadrzędnej, jeśli istnieje więcej niż jeden rekord potomny z nim związany, ponieważ JOIN zwraca wiersze, które są zgodne. Co oznacza, że ​​jeśli chcesz używać unikatowych wartości z tabeli nadrzędnej podczas korzystania z powiązań JOIN, musisz rozważyć użycie klauzuli DISTINCT lub GROUP BY. Ale nic z tego nie jest problemem, jeśli używane jest podzapytanie.

Ponadto podkwerendy nie są takie same. Nie ma prostej oceny, jak Twój przykład:

where emp.id = (select s.id from sap s where s.id = 111) 

... a klauzula:

where emp.id IN (select s.id from sap s where s.id = 111) 

... który będzie pasował do żadnej z wartości (S) zwracany przez podzapytanie, gdy prosta ocena spowoduje błąd, jeśli s.id zwróci więcej niż jedną wartość. Ale jest też klauzula EXISTS ...

WHERE EXISTS(SELECT NULL 
       FROM SAP s 
       WHERE emp.id = s.id 
       AND s.id = 111) 

EXISTS różni się tym, że:

  • klauzuli SELECT nie zostanie oceniony - można go zmienić na SELECT 1/0, który powinien wyzwalania błąd dzielenia przez zero, ale nie będzie zwracał wartości true/false; prawda jest oparta na pierwszym przypadku, gdy kryteria są spełnione, więc jest szybszy w przypadku duplikatów.
  • w przeciwieństwie do klauzuli IN, EXISTS obsługuje porównywanie dwóch lub więcej porównań kolumn w tym samym czasie, ale niektóre bazy danych obsługują porównanie krotek z IN.
  • jest bardziej czytelny
+0

+1, dziękuję za dokładną odpowiedź. –

+0

Czy sądzisz, że są sytuacje, w których klauzula "IN" jest lepsza niż "EXISTS"? –

+1

@Daniel Vassallo: Nie w tej chwili. Zastanawiam się, że podejście EXISTS omija również problem z dużą liczbą wartości do porównania z IN w niektórych bazach danych (w tysiącach). –

0

Jest to o wiele szybciej (i łatwiej napisać) do łączenia dwóch tabel na indeksie niż bieg dwa oddzielne zapytania (nawet podzapytanie).

+0

Ale dlaczego? Jaka jest różnica w planie wykonania? –

+0

Nie ma różnicy, ponieważ MySQL zoptymalizuje ją, by prawdopodobnie użyć JOIN i zrobić to samo, ale zobaczysz, że uruchamia zapytanie PRIMARY i SUBQUERY. Nie wiem, czy ma to wpływ na prędkość. Inną rzeczą jest to, że semantycznie dołączasz do dwóch tabel, więc dlaczego by tego nie pisać? –

+0

@tandu, myślę, że dla wielu zapytań, podkwerendy oferują większą jasność. Jeśli chcesz tylko jeden kawałek danych z drugiej tabeli, * jest * bardziej * jasne, aby wszystko było w jednym miejscu (z podzapytaniem) niż podzielić je na wybrane, z/join, i potencjalnie tam, gdzie Klauzula pierwotnego zapytania. –

1

Jeśli zapytania są logicznie równoważne, to optymalizator zapytań powinien móc wykonać taki sam (najlepszy) plan wykonania z każdego z nich. W takim przypadku styl zapytania powinien obsługiwać to, co można najlepiej zrozumieć (to podzadania dla mnie).