Składnia ŁĄCZENIA WEWNĘTRZNEGO zagnieżdżonego wewnątrz ŁĄCZENIA ZEWNĘTRZNEGO a wyniki zapytań

10

TLDR; Jeśli spojrzysz na 2 plany wykonania, czy jest łatwa odpowiedź na to, co jest lepsze? Celowo NIE tworzyłem indeksów, więc łatwiej jest zobaczyć, co się dzieje.

Kontynuując moje poprzednie pytanie, w którym znaleźliśmy różnicę w wydajności zapytania między różnymi stylami łączenia (tj. Zagnieżdżone vs. tradycyjne), zdałem sobie sprawę, że zagnieżdżona składnia również modyfikuje zachowanie zapytania. Rozważ następujące 2 zapytania.

SELECT  a.*, m.*, n.*
FROM    dbo.Autos a
LEFT JOIN dbo.Models m
  JOIN dbo.Manufacturers n  -- <-- Nested INNER JOIN
  ON n.ManufacturerID = m.ManufacturerID
ON m.ModelID = a.ModelID

wprowadź opis zdjęcia tutaj

Nie musi to powodować, że producenci dołączają, aby dołączyć automatyczny wiersz o ModelID, który NIE znajduje się w tabeli Modele.

wprowadź opis zdjęcia tutaj

Używając tradycyjnej składni, musimy zmienić złączenie na Produkcja na złączenie zewnętrzne, tak jak ... ale to zmienia plan zapytań.

SELECT a.*, m.*, n.*
FROM dbo.Autos a
LEFT JOIN dbo.Models m
ON m.ModelID = a.ModelID
LEFT JOIN dbo.Manufacturers n -- <-- Now LEFT OUTER JOIN
ON n.ManufacturerID = m.ManufacturerID

wprowadź opis zdjęcia tutaj

JeffInCO
źródło

Odpowiedzi:

12

Jeśli spojrzysz na 2 plany wykonania, czy jest łatwa odpowiedź na to, co jest lepsze? Celowo NIE tworzyłem indeksów, więc łatwiej jest zobaczyć, co się dzieje.

Drugi plan ma niższy szacowany koszt, więc w tym ograniczonym znaczeniu jest „lepszy”.

Zestawy danych są tak małe, że optymalizator nie spędził dużo czasu na szukaniu alternatyw. Pierwsza forma zapytania zdarza się, aby wcześnie znaleźć plan, używając skrótu łączenia i buforu tabeli. Szacunkowy koszt tego planu jest tak niski, że optymalizator nie zawraca sobie głowy szukaniem czegoś lepszego.

Druga forma zapytania zdarza się znaleźć plan wykorzystujący tylko sprzężenia zewnętrzne z zagnieżdżonymi pętlami na początku procesu wyszukiwania, i ponownie optymalizator decyduje, że plan jest wystarczająco dobry. Zdarza się, że plan ten jest tańszy.

To powiedziawszy (jak wspomniano w komentarzach do pytania), dwa zapytania nie są semantycznie identyczne. Może to nie być dla Ciebie ważne, jeśli możesz zagwarantować, że wyniki będą zawsze takie same dla wszystkich możliwych przyszłych stanów bazy danych, ale optymalizator nie może przyjąć tego założenia. Tworzy tylko plany, które gwarantują uzyskanie takich samych wyników określonych przez SQL we wszystkich okolicznościach.

Zdałem sobie sprawę, że zagnieżdżona składnia również modyfikuje zachowanie zapytania.

„Zagnieżdżona składnia” jest tylko jednym aspektem całej specyfikacji składni ANSI. Aby włączyć pełną logiczną specyfikację dla bardziej złożonych wzorców łączenia, specyfikacja dopuszcza (opcjonalne) nawiasy i FROMpodzapytania klauzul.

Zapytanie można napisać przy użyciu tej samej składni ANSI, używając nawiasów:

SELECT
    A.*,
    M.*,
    N.* 
FROM dbo.Autos AS A
LEFT JOIN
(
    dbo.Manufacturers AS N
    JOIN dbo.Models AS M
        ON M.ManufacturerID = N.ManufacturerID
) ON M.ModelID = A.ModelID;

Ta forma wyraźnie pokazuje, że wymóg logiczne jest, aby dołączyć z lewej Autosna skutek wewnętrznego łączenia Manufacturerssię Models. Pominięcie opcjonalnych nawiasów daje formę, którą nazywasz „zagnieżdżoną”:

SELECT
    A.*,
    M.*,
    N.* 
FROM dbo.Autos AS A
LEFT JOIN dbo.Manufacturers AS N
JOIN dbo.Models AS M
    ON M.ManufacturerID = N.ManufacturerID
    ON M.ModelID = A.ModelID;

To nie jest inna składnia - po prostu pomija się opcjonalne nawiasy i nieco formatuje.

Jak wspomniano Martin, w tym przypadku możliwe jest również wyrażenie logicznego wymogu za pomocą złączeń wewnętrznych, a następnie prawego łączenia zewnętrznego:

SELECT
    A.*,
    M.*,
    N.* 
FROM dbo.Manufacturers AS N
JOIN dbo.Models AS M
    ON M.ManufacturerID = N.ManufacturerID
RIGHT JOIN dbo.Autos AS A
    ON A.ModelID = M.ModelID;

Wszystkie trzy powyższe formularze zapytań używają tej samej składni złączenia ANSI. Wszystkie trzy tworzą również ten sam fizyczny plan wykonania z dostarczonym zestawem danych:

Wspólny plan wykonania

Jak wspomniałem w mojej odpowiedzi na twoje poprzednie pytanie, zapytania, które wyrażają dokładnie to samo wymaganie logiczne, nie zawsze dają ten sam plan wykonania. Wybór logicznej formy zapytania jest w dużej mierze kwestią stylu. Nie ma korelacji między jednym konkretnym stylem a ogólnie „lepszymi” planami zapytań. Generalnie odradzam przepisywanie zapytania, aby uzyskać konkretny plan, jeśli nowe zapytanie nie jest autentycznie logicznie identyczne z oryginałem.

Standard SQL dopuszcza również FROMpodzapytania klauzul, więc jeszcze innym sposobem napisania tej samej specyfikacji zapytania jest:

SELECT * 
FROM dbo.Autos AS A
LEFT JOIN
(
    SELECT
        N.ManufacturerID,
        ManufacturerName = N.Name,
        M.ModelID,
        ModelName = M.Name
    FROM dbo.Manufacturers AS N
    JOIN dbo.Models AS M
        ON M.ManufacturerID = N.ManufacturerID
) AS R1
    ON R1.ModelID = A.ModelID;

Używając tradycyjnej składni, musimy zmienić złączenie na `Producenci na złączenie zewnętrzne, tak jak ... ale to zmienia plan zapytań.

To prawdopodobnie zmienia znaczenie zapytaniu, w tym przypadku nie jest technicznie poprawny alternatywa (ale patrz ypercube „s komentarz na pytanie).

(Opcjonalne) nawiasy w składni złączenia ANSI są właśnie dla bardziej złożonych wymagań łączenia, takich jak ten, więc nie powinieneś obawiać się ich używania w razie potrzeby.

Paul White 9
źródło