Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Wydajność INNER JOIN vs LEFT JOIN w SQL Server

LEFT JOIN jest absolutnie nie szybszy niż INNER JOIN . W rzeczywistości jest wolniejszy; z definicji sprzężenie zewnętrzne (LEFT JOIN lub RIGHT JOIN ) musi wykonać całą pracę INNER JOIN plus dodatkowa praca polegająca na rozszerzaniu wyników o wartości zerowej. Oczekuje się również, że zwróci więcej wierszy, co dodatkowo zwiększy całkowity czas wykonania po prostu ze względu na większy rozmiar zestawu wyników.

(I nawet jeśli LEFT JOIN było szybciej w konkretnych sytuacji z powodu trudnej do wyobrażenia konfluencji czynników, nie jest funkcjonalnie równoważny z INNER JOIN , więc nie możesz po prostu zastąpić wszystkich wystąpień jednego z drugim!)

Najprawdopodobniej Twoje problemy z wydajnością leżą gdzie indziej, na przykład nie mając odpowiednio zindeksowanego klucza kandydującego lub klucza obcego. 9 stołów to całkiem sporo, więc spowolnienie może być dosłownie wszędzie. Jeśli opublikujesz swój schemat, być może będziemy mogli podać więcej szczegółów.

Edytuj:

Zastanawiając się dalej nad tym, mogłem wymyślić jedną okoliczność, w której LEFT JOIN może być szybszy niż INNER JOIN , i to wtedy:

  • Niektóre tabele są bardzo mały (powiedzmy, poniżej 10 rzędów);
  • Tabele nie mają wystarczającej liczby indeksów, aby objąć zapytanie.

Rozważ ten przykład:

CREATE TABLE #Test1
(
    ID int NOT NULL PRIMARY KEY,
    Name varchar(50) NOT NULL
)
INSERT #Test1 (ID, Name) VALUES (1, 'One')
INSERT #Test1 (ID, Name) VALUES (2, 'Two')
INSERT #Test1 (ID, Name) VALUES (3, 'Three')
INSERT #Test1 (ID, Name) VALUES (4, 'Four')
INSERT #Test1 (ID, Name) VALUES (5, 'Five')

CREATE TABLE #Test2
(
    ID int NOT NULL PRIMARY KEY,
    Name varchar(50) NOT NULL
)
INSERT #Test2 (ID, Name) VALUES (1, 'One')
INSERT #Test2 (ID, Name) VALUES (2, 'Two')
INSERT #Test2 (ID, Name) VALUES (3, 'Three')
INSERT #Test2 (ID, Name) VALUES (4, 'Four')
INSERT #Test2 (ID, Name) VALUES (5, 'Five')

SELECT *
FROM #Test1 t1
INNER JOIN #Test2 t2
ON t2.Name = t1.Name

SELECT *
FROM #Test1 t1
LEFT JOIN #Test2 t2
ON t2.Name = t1.Name

DROP TABLE #Test1
DROP TABLE #Test2

Jeśli uruchomisz to i przejrzysz plan wykonania, zobaczysz, że INNER JOIN zapytanie rzeczywiście kosztuje więcej niż LEFT JOIN , ponieważ spełnia dwa powyższe kryteria. Dzieje się tak, ponieważ SQL Server chce wykonać dopasowanie skrótu dla INNER JOIN , ale robi zagnieżdżone pętle dla LEFT JOIN; pierwszy to normalnie znacznie szybciej, ale ponieważ liczba wierszy jest tak mała i nie ma indeksu do użycia, operacja haszowania okazuje się być najdroższą częścią zapytania.

Możesz zobaczyć ten sam efekt, pisząc program w swoim ulubionym języku programowania, aby wykonać dużą liczbę wyszukiwań na liście z 5 elementami, w porównaniu z tabelą mieszającą z 5 elementami. Ze względu na rozmiar wersja tablicy mieszającej jest w rzeczywistości wolniejsza. Ale zwiększ go do 50 elementów lub 5000 elementów, a wersja listy spowalnia się do indeksowania, ponieważ dla tablicy mieszającej jest O(N) kontra O(1).

Ale zmień to zapytanie na ID kolumna zamiast Name a zobaczysz zupełnie inną historię. W takim przypadku wykonuje zagnieżdżone pętle dla obu zapytań, ale INNER JOIN wersja jest w stanie zastąpić jedno ze skanowanych indeksów klastrowych wyszukiwaniem - co oznacza, że ​​będzie to dosłownie o rząd wielkości szybciej z dużą liczbą rzędów.

Tak więc wniosek jest mniej więcej taki, jak wspomniałem w kilku akapitach powyżej; jest to prawie na pewno problem z indeksowaniem lub pokryciem indeksu, prawdopodobnie w połączeniu z jedną lub kilkoma bardzo małymi tabelami. To jedyne okoliczności, w których SQL Server może czasami wybieraj gorszy plan wykonania dla INNER JOIN niż LEFT JOIN .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Server - połącz się z uwierzytelnianiem Windows

  2. Użyj TYPEPROPERTY(), aby zwrócić informacje o typie danych w SQL Server

  3. Jak sys.dm_exec_describe_first_result_set działa w SQL Server

  4. Jak zwrócić bieżącą wartość rowversion dla bazy danych programu SQL Server (przykład T-SQL)

  5. Połącz SQL Server z SugarCRM