Co jest lepsze: wielu łączy warunki lub wiele warunków, w których?


13

Próbuję porównać dwa zapytania:

Zapytanie 1:

SELECT a,b,c,d,e
FROM tableA
LEFT JOIN tableB
ON tableA.a=tableB.a
WHERE tableA.b=tableB.b AND tableA.c=tableB.c  AND tableA.d=tableB.d  AND tableA.e=tableB.e 

Zapytanie 2:

SELECT a,b,c,d,e
FROM tableA
LEFT JOIN tableB
ON tableA.a=tableB.a AND tableA.b=tableB.b AND tableA.c=tableB.c  AND tableA.d=tableB.d  
WHERE tableA.e=tableB.e 

Czy mam rację twierdząc, że te dwa zapytania dają takie same wyniki?

Ponadto, czy słuszne jest stwierdzenie, że pierwsze zapytanie buduje większą tabelę, dla której można wykonać większy WHEREwarunek; podczas gdy w drugim przypadku mamy mniejszą tabelę, do której WHEREnastępnie stosuje się prosty .

Zakładając, że wyniki są takie same, które zapytanie powinno być preferowane? Czy jest oczywisty problem z wydajnością?


3
Nie, nie masz racji mówiąc. Byłoby, gdyby to był INNER JOIN, ale z LEFT JOINtym zwróci inne wyniki. Zasadniczo, warunki, które zostały dodane na WHEREna drugim zapytaniu są konwersja JOINna zasadzieINNER JOIN
— Lamak

Ach ok. Śledzę to, co mówisz. Jeśli dokonam edycji, aby INNER JOINmoje pytania dotyczące wydajności pozostały ważne?
— Geoff,

4
W przypadku ŁĄCZNIKÓW WEWNĘTRZNYCH nie powinno być żadnej różnicy w wydajności. To powiedziawszy, dla czytelności i właściwego wyrażenia intencji, powinieneś użyć kryteriów łączenia w ONi kryteriów filtrowania w WHERE.
— Aaron Bertrand

@ypercube racja, brakowało mi tego warunku.
— Lamak

Odpowiedzi:


10

Jeśli uznamy, że używasz INNER JOINzamiast LEFT JOIN(co wydaje się twoim zamiarem), te dwa zapytania są funkcjonalnie równoważne. Optymalizatory zapytań sprawdzą i ocenią kryteria zawarte w WHEREklauzuli i FROMklauzuli oraz wezmą pod uwagę wszystkie te czynniki przy tworzeniu planów zapytań w celu osiągnięcia najbardziej wydajnego planu wykonania. Jeśli zrobimy EXPLAINna obu instrukcjach, otrzymamy ten sam wynik:

Zapytanie 1 :

EXPLAIN
SELECT 
  tableA.ColA
  ,tableA.ColB
  ,tableA.ColC
  ,tableA.ColD
  ,tableA.ColE
FROM tableA
  JOIN tableB ON tableA.ColA=tableB.ColA
WHERE 
  tableA.ColB=tableB.ColB 
  AND tableA.ColC=tableB.ColC 
  AND tableA.ColD=tableB.ColD  
  AND tableA.ColE=tableB.ColE

[Wyniki] :

| ID | SELECT_TYPE |  TABLE | TYPE | POSSIBLE_KEYS |    KEY | KEY_LEN |    REF | ROWS |                          EXTRA |
------------------------------------------------------------------------------------------------------------------------
|  1 |      SIMPLE | tableA |  ALL |        (null) | (null) |  (null) | (null) |    1 |                                |
|  1 |      SIMPLE | tableB |  ALL |        (null) | (null) |  (null) | (null) |    1 | Using where; Using join buffer |

Zapytanie 2 :

EXPLAIN
SELECT 
  tableA.ColA
  ,tableA.ColB
  ,tableA.ColC
  ,tableA.ColD
  ,tableA.ColE
FROM tableA
  JOIN tableB ON tableA.ColA=tableB.ColA
  AND tableA.ColB=tableB.ColB 
  AND tableA.ColC=tableB.ColC 
  AND tableA.ColD=tableB.ColD  
WHERE
  tableA.ColE=tableB.ColE

[Wyniki] :

| ID | SELECT_TYPE |  TABLE | TYPE | POSSIBLE_KEYS |    KEY | KEY_LEN |    REF | ROWS |                          EXTRA |
------------------------------------------------------------------------------------------------------------------------
|  1 |      SIMPLE | tableA |  ALL |        (null) | (null) |  (null) | (null) |    1 |                                |
|  1 |      SIMPLE | tableB |  ALL |        (null) | (null) |  (null) | (null) |    1 | Using where; Using join buffer |

Możesz przejrzeć pełne informacje za pomocą poniższych linków. Stworzyłem również przykład SQL 2008, abyś mógł porównać działanie dwóch silników (co jest takie samo):

Przykład zapytania MySQL

Przykład zapytania w SQL 2008 (upewnij się, że „wyświetlasz plan wykonania” dla obu wyników)


Dziękujemy za szczegółowe rozwiązanie. Próbowałem INNER JOINzamiast LEFT JOINi uzyskuję ten sam wynik w dziesiątej części czasu. Chyba wiem, dlaczego otrzymuję taką samą moc wyjściową, ale dlaczego miałbym INNER JOINlepszą wydajność?
— Geoff,

4
Podobnie LEFT JOINjak sprzężenie zewnętrzne, nie może ograniczyć zestawu danych po pełnej stronie powrotu zestawu i spróbuje pobrać wszystkie wiersze z tej tabeli (w tym przypadku TableA). Jeśli używasz INNER JOIN, może wykorzystać te kryteria w obu tabelach i ograniczyć zestaw danych, zapewniając w ten sposób szybszy zwrot.
— Mike Fal
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.