Optymalizacja podstawowych zapytań z łączeniem tabel.

0

Mam takie 2 zapytania proste:

SELECT *
FROM EMP e
            INNER JOIN CAR c ON e.IdPrac = c.IdPrac AND e.IdPrac = 1;

oraz

SELECT *
FROM EMP e
            INNER JOIN CAR c ON e.IdPrac = 1 AND c.IdPrac = 1;

Czy istnieje w nich jakakoliwek różnica wydajności czy w rzeczywistości silnik przetwarza je tak samo?
Na moją logikę w pierwszym przypadku po wyliczeniu iloczynu kartezjańskiego, przeszukiwane są wszystko połączenia wspólne ( odfiltrowana część wyników) i dopiero potem filtrowane pojedyńcze id.
W drugim operacja filtracja obrabia 2 razy taki sam pełen zbiór. Czy to ma znaczenie w tym przypadku?

1

Nie powinno być żadnej różnicy. Nie mam teraz MySQL pod ręką ale na MSSQL nie będzie różnicy w wydajności obu tych zapytań.

2

A co do tej strony sqlpedia to opis inner joina wydaje mi się niezbyt szczęśliwy. A przykład:

SELECT * 
FROM dbo.EMP e INNER JOIN dbo.CAR c ON e.IdPrac = 1

jest wybitnie antyedukacyjny. Miejsce tego typu kodu jest na śmietniku.

Poprawny zapis to:
SELECT *
FROM dbo.EMP e INNER JOIN dbo.CAR c ON e.IdPrac = c.IdPrac
WHERE e.IdPrac = 1

Wtedy jasno widać co jest złączeniem, a co warunkiem filtrującym.

Trzeba też zaznaczyć, że o ile dla INNER JOIN warunek filtrujący w ON czy WHERE nie ma znaczenia (zawężenie do IdPrac), to w przypadku OUTER JOIN może zupełnie zmienić wynik zapytania.

0

@robertos7778: przykład, który podałeś jest na tym blogu opisany jako błąd więc raczej wszystko się zgadza, choć faktycznie jak teraz testuje to co napisałeś, mógł dokładniej opisać przypadek.
Czy w takim razie w warunku ON zawsze ma być tylko warunek złączenia tabel, a jakiekolwiek filtracje powinny zawsze wykonywane w WHERE?

Np.
Niepoprawnie:

SELECT e.IdPrac, e.Imie, e.DtZatr, c.Marka, c.NrRej
FROM EMP e
       INNER JOIN CAR c ON e.IdPrac = c.IdPrac AND YEAR(e.DtZatr) >= 2011;

Poprawnie:

SELECT e.IdPrac, e.Imie, e.DtZatr, c.Marka, c.NrRej
FROM EMP e
       INNER JOIN CAR c ON e.IdPrac = c.IdPrac
WHERE YEAR(e.DtZatr) >= 2011;

Czy przypadki kiedy nie chcemy odfiltrowywać zewnętrzengo zbioru istnieją i filtracja w ON jestw nich porawna?

1

Dla czytelności ON powinien zawierać złączenia, a WHERE warunki filtrujące. To co napisałeś jest równoważne w przypadku INNER JOIN.

Ale tak jak napisałem, w przypadku LEFT/RIGHT JOIN to gdzie wystąpi warunek filtrujący, ma wpływ na wynik zapytania. Umieszczasz go w odpowiednim miejscu zależnie od tego, czy chcesz najpierw odrzucić rekordy wg filtra, a potem je złączyć czy też odwrotnie. Oczywiście ma to znaczenie, gdy filtr dotyczy tabeli dołączanej, w której brakuje rekordów spełniających warunek złączenia (czyli dla left join - tej, której występuje po prawej stronie ON).

1 użytkowników online, w tym zalogowanych: 0, gości: 1