Optymalizacja podstawowych zapytań z łączeniem tabel.

Optymalizacja podstawowych zapytań z łączeniem tabel.
Prędki_Lopez
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 253
0

Mam takie 2 zapytania proste:

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

oraz

Kopiuj
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?

Haskell
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 4700
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ń.

R7
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 216
2

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

Kopiuj
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.

Prędki_Lopez
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 253
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:

Kopiuj
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:

Kopiuj
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?

R7
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 216
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).

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.