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 FROM
podzapytania 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 Autos
na skutek wewnętrznego łączenia Manufacturers
się 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:
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ż FROM
podzapytania 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.