Mam tabelę (MainTable
) z nieco ponad 600 000 rekordów. Łączy na siebie poprzez 2nd tabeli (JoinTable
) w relacji typu rodzic/dziecko:LEFT JOIN Znacząco szybszy niż INNER DOŁĄCZ
SELECT Child.ID, Parent.ID
FROM MainTable
AS Child
JOIN JoinTable
ON Child.ID = JoinTable.ID
JOIN MainTable
AS Parent
ON Parent.ID = JoinTable.ParentID
AND Parent.SomeOtherData = Child.SomeOtherData
Wiem, że każde dziecko ma rekord rekord nadrzędny a dane w JoinTable jest acurate.
Po uruchomieniu tego zapytania trwa dosłownie kilka minut. Jednak jeśli mogę dołączyć do dominującej przy użyciu LEFT JOIN następnie zajmuje < 1 sekundę, aby uruchomić:
SELECT Child.ID, Parent.ID
FROM MainTable
AS Child
JOIN JoinTable
ON Child.ID = JoinTable.ID
LEFT JOIN MainTable
AS Parent
ON Parent.ID = JoinTable.ParentID
AND Parent.SomeOtherData = Child.SomeOtherData
WHERE ...[some info to make sure we don't select parent records in the child dataset]...
Rozumiem różnicę między wynikami w INNER JOIN
i LEFT JOIN
. W tym przypadku zwraca dokładnie taki sam wynik, jak każde dziecko ma rodzica. Jeśli pozwolę obu zadaniom uruchomić, mogę porównać zestawy danych i są one dokładnie takie same.
Dlaczego to LEFT JOIN
działa o wiele szybciej niż INNER JOIN
?
UPDATE sprawdzone plany zapytań i przy użyciu sprzężenie wewnętrzne zaczyna się w zbiorze dominującej. Podczas łączenia lewego zaczyna się od zbioru danych podrzędnego.
Indeksy, których używa, są takie same.
Czy mogę zmusić go, aby zawsze zaczynał od dziecka? Używanie lewego sprzężenia działa, po prostu wydaje się nie tak.
Podobne pytania zadawano wcześniej, ale nikt nie odpowiedział na moje pytanie.
np. wybrana odpowiedź w INNER JOIN vs LEFT JOIN performance in SQL Server mówi, że lewe połączenia są zawsze wolniejsze niż wewnętrzne połączenia. Argument ma sens, ale to nie jest to, co widzę.
Sprawdź plany. – Blorgbeard
@Blogbeard - patrz aktualizacja – Greg