INNER JOIN vs wydajność LEFT JOIN w SQL Server

259

Utworzyłem polecenie SQL, które używa INNER JOIN na 9 stołach, w każdym razie to polecenie zajmuje bardzo dużo czasu (ponad pięć minut). Więc mój lud zaproponował mi zmianę INNER JOIN na LEFT JOIN, ponieważ wydajność LEFT JOIN jest lepsza, pomimo tego, co wiem. Po jego zmianie szybkość zapytania znacznie się poprawiła.

Chciałbym wiedzieć, dlaczego LEFT JOIN jest szybszy niż INNER JOIN?

Moje polecenie SQL wygląda jak poniżej: SELECT * FROM A INNER JOIN B ON ... INNER JOIN C ON ... INNER JOIN Di tak dalej

Aktualizacja: To jest skrót mojego schematu.

FROM sidisaleshdrmly a -- NOT HAVE PK AND FK
    INNER JOIN sidisalesdetmly b -- THIS TABLE ALSO HAVE NO PK AND FK
        ON a.CompanyCd = b.CompanyCd 
           AND a.SPRNo = b.SPRNo 
           AND a.SuffixNo = b.SuffixNo 
           AND a.dnno = b.dnno
    INNER JOIN exFSlipDet h -- PK = CompanyCd, FSlipNo, FSlipSuffix, FSlipLine
        ON a.CompanyCd = h.CompanyCd
           AND a.sprno = h.AcctSPRNo
    INNER JOIN exFSlipHdr c -- PK = CompanyCd, FSlipNo, FSlipSuffix
        ON c.CompanyCd = h.CompanyCd
           AND c.FSlipNo = h.FSlipNo 
           AND c.FSlipSuffix = h.FSlipSuffix 
    INNER JOIN coMappingExpParty d -- NO PK AND FK
        ON c.CompanyCd = d.CompanyCd
           AND c.CountryCd = d.CountryCd 
    INNER JOIN coProduct e -- PK = CompanyCd, ProductSalesCd
        ON b.CompanyCd = e.CompanyCd
           AND b.ProductSalesCd = e.ProductSalesCd 
    LEFT JOIN coUOM i -- PK = UOMId
        ON h.UOMId = i.UOMId 
    INNER JOIN coProductOldInformation j -- PK = CompanyCd, BFStatus, SpecCd
        ON a.CompanyCd = j.CompanyCd
            AND b.BFStatus = j.BFStatus
            AND b.ProductSalesCd = j.ProductSalesCd
    INNER JOIN coProductGroup1 g1 -- PK = CompanyCd, ProductCategoryCd, UsedDepartment, ProductGroup1Cd
        ON e.ProductGroup1Cd  = g1.ProductGroup1Cd
    INNER JOIN coProductGroup2 g2 -- PK = CompanyCd, ProductCategoryCd, UsedDepartment, ProductGroup2Cd
        ON e.ProductGroup1Cd  = g2.ProductGroup1Cd
Anonimowy
źródło
1
Czy wyświetlasz jakiś atrybut coUOM? Jeśli nie, możesz użyć połączenia częściowo. Jeśli tak, będziesz mógł skorzystać UNIONz alternatywy. Publikowanie tylko FROMklauzuli jest tutaj nieodpowiednimi informacjami.
poniedziałek
1
Zastanawiałem się tak często (bo cały czas widzę).
Paul Draper,
1
Czy przegapiłeś Order By w swoim krótkim schemacie? Niedawno napotkałem problem polegający na tym, że zmiana WEJŚCIA WEWNĘTRZNEGO na POŁĄCZENIE ZEWNĘTRZNE przyspiesza zapytanie z 3 minut do 10 sekund. Jeśli naprawdę masz Order By w zapytaniu, wyjaśnię dalej jako odpowiedź. Wyglądało na to, że wszystkie odpowiedzi tak naprawdę nie wyjaśniały sprawy, z którą się spotkałem.
Phuah Yee Keat,

Odpowiedzi:

403

A nie LEFT JOINjest absolutnie szybszy niż INNER JOIN. W rzeczywistości jest wolniejszy; z definicji połączenie zewnętrzne ( LEFT JOINlub RIGHT JOIN) musi wykonać całą pracę INNER JOINplus dodatkową pracę polegającą na przedłużeniu wartości null wyników. 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ły szybsze w określonych sytuacjach z powodu trudnej do wyobrażenia zbieżności czynników, nie jest to funkcjonalnie równoważne z INNER JOIN, więc nie można po prostu zastąpić wszystkich wystąpień jednego z nich drugim!)

Najprawdopodobniej problemy z wydajnością leżą gdzie indziej, na przykład brak prawidłowego indeksowania klucza kandydującego lub klucza obcego. 9 stołów to całkiem sporo, więc spowolnienie może dosłownie być niemal wszędzie. Jeśli opublikujesz swój schemat, możemy podać więcej szczegółów.


Edytować:

Zastanawiając się nad tym, mógłbym pomyśleć o jednej okoliczności, w której a LEFT JOINmoże być szybsze niż an INNER JOIN, i wtedy:

  • Niektóre tabele są bardzo małe (powiedzmy, poniżej 10 rzędów);
  • Tabele nie mają wystarczających indeksów do pokrycia zapytania.

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 JOINzapytanie rzeczywiście kosztuje więcej niż LEFT JOIN, ponieważ spełnia dwa powyższe kryteria. Jest tak, ponieważ SQL Server chce dopasować skrót dla INNER JOIN, ale zagnieżdżone pętle dla LEFT JOIN; pierwsze jest zwykle znacznie szybsze, ale ponieważ liczba wierszy jest tak mała i nie ma indeksu do użycia, operacja mieszania okazuje się być najdroższą częścią zapytania.

Możesz zobaczyć ten sam efekt, pisząc program w swoim ulubionym języku programowania do wykonywania dużej liczby wyszukiwań na liście zawierającej 5 elementów, w porównaniu do tabeli mieszającej z 5 elementami. Ze względu na rozmiar wersja tabeli skrótów jest wolniejsza. Ale zwiększ go do 50 elementów lub 5000 elementów, a wersja listy spowalnia do indeksowania, ponieważ jest to O (N) vs. O (1) dla tablicy mieszającej.

Ale zmień to zapytanie na IDkolumnę zamiast, Namea zobaczysz zupełnie inną historię. W takim przypadku wykonuje zagnieżdżone pętle dla obu zapytań, ale INNER JOINwersja jest w stanie zastąpić jedno ze skanów indeksu klastrowego wyszukiwaniem - co oznacza, że ​​będzie to dosłownie o rząd wielkości szybsze z dużą liczbą wierszy.

Wniosek jest mniej więcej tym, o czym wspominałem kilka akapitów powyżej; prawie na pewno jest to problem z indeksowaniem lub pokryciem indeksu, prawdopodobnie w połączeniu z jedną lub kilkoma bardzo małymi tabelami. Są to jedyne okoliczności, w których SQL Server może czasami wybrać gorszy plan wykonania dla INNER JOINniż niż LEFT JOIN.

Aaronaught
źródło
4
Istnieje inny scenariusz, który może doprowadzić do tego, że ZŁĄCZE ZEWNĘTRZNE osiąga lepsze wyniki niż DOŁĄCZENIE ZEWNĘTRZNE. Zobacz moją odpowiedź poniżej.
dbenham
12
Chcę zauważyć, że w zasadzie nie ma dokumentacji bazy danych, która wspierałaby tezę, że połączenia wewnętrzne i połączenia zewnętrzne działają inaczej. Sprzężenia zewnętrzne są nieco droższe niż sprzężenia wewnętrzne, ze względu na objętość danych i rozmiar zestawu wyników. Jednak podstawowe algorytmy ( msdn.microsoft.com/en-us/library/ms191426(v=sql.105).aspx ) są takie same dla obu typów złączeń. Wydajność powinna być podobna, gdy zwracają podobne ilości danych.
Gordon Linoff,
3
@Aaronaught. . . Do odpowiedzi wspomniano w komentarzu, który powiedział coś, że „łączenia zewnętrzne działają znacznie gorzej niż połączenia wewnętrzne”. Skomentowałem tylko, aby mieć pewność, że ta błędna interpretacja się nie rozprzestrzeni.
Gordon Linoff,
16
Myślę, że ta odpowiedź wprowadza w błąd w jednym ważnym aspekcie: Ponieważ stwierdza, że ​​„POŁĄCZENIE W LEWO nie jest absolutnie szybsze niż DOŁĄCZENIE WEWNĘTRZNE”. Ta linia jest nieprawidłowa. Jest to teoretycznie nie szybciej niż INNER JOIN. NIE jest to „absolutnie nie szybsze”. Pytanie dotyczy w szczególności wydajności. W praktyce widziałem teraz kilka systemów (bardzo dużych firm!), W których INNER JOIN był absurdalnie wolny w porównaniu do OUTER JOIN. Teoria i praktyka to bardzo różne rzeczy.
David Frenkel
5
@DavidFrenkel: Jest to bardzo mało prawdopodobne. Chciałbym zobaczyć porównanie A / B z planami wykonania, jeśli uważasz, że taka rozbieżność jest możliwa. Być może jest to związane z buforowanymi planami zapytań / wykonania lub złymi statystykami.
Aaronaught
127

Jest jeden ważny scenariusz, który może doprowadzić do tego, że połączenie zewnętrzne jest szybsze niż połączenie wewnętrzne, które nie zostało jeszcze omówione.

Podczas korzystania z zewnętrznego połączenia optymalizator zawsze może upuścić zewnętrzną połączoną tabelę z planu wykonania, jeśli kolumny łączenia są PK tabeli zewnętrznej i żadna z kolumn tabeli zewnętrznej nie jest przywoływana poza samym złączem zewnętrznym. Na przykład SELECT A.* FROM A LEFT OUTER JOIN B ON A.KEY=B.KEYB.KEY to PK dla B. Zarówno Oracle (myślę, że korzystałem z wersji 10), jak i Sql Server (użyłem 2008 R2) tabeli przycinania B z planu wykonania.

To samo niekoniecznie jest prawdą dla połączenia wewnętrznego: SELECT A.* FROM A INNER JOIN B ON A.KEY=B.KEY może, ale nie musi wymagać B w planie wykonania, w zależności od istniejących ograniczeń.

Jeśli A.KEY jest zerowalnym kluczem obcym odwołującym się do B.KEY, optymalizator nie może usunąć B z planu, ponieważ musi potwierdzić, że wiersz B istnieje dla każdego wiersza A.

Jeśli A.KEY jest obowiązkowym kluczem obcym odwołującym się do B.KEY, optymalizator może usunąć B z planu, ponieważ ograniczenia gwarantują istnienie wiersza. Ale to, że optymalizator może usunąć tabelę z planu, nie oznacza, że ​​tak będzie. SQL Server 2008 R2 NIE usuwa B z planu. Wyrocznia 10 Zrzuca B z planu. W tym przypadku łatwo jest zobaczyć, jak zewnętrzne połączenie wykona wewnętrzne połączenie na SQL Server.

Jest to trywialny przykład i niepraktyczny w przypadku samodzielnego zapytania. Po co dołączać do stołu, jeśli nie potrzebujesz?

Ale może to być bardzo ważne przy projektowaniu widoków. Często budowany jest widok „rób wszystko”, który łączy wszystko, czego użytkownik może potrzebować w związku z centralnym stołem. (Zwłaszcza jeśli naiwni użytkownicy wykonują zapytania ad-hoc, które nie rozumieją modelu relacyjnego) Widok może zawierać wszystkie odpowiednie kolumny z wielu tabel. Ale użytkownicy końcowi mogą uzyskiwać dostęp do kolumn tylko z podzestawu tabel w widoku. Jeśli tabele są połączone zewnętrznymi złączeniami, optymalizator może (i robi) usunąć niepotrzebne tabele z planu.

Bardzo ważne jest, aby upewnić się, że widok przy użyciu złączeń zewnętrznych daje prawidłowe wyniki. Jak powiedział Aaronaught - nie możesz na ślepo zastąpić DOŁĄCZENIA ZEWNĘTRZNEGO do DOŁĄCZENIA WEWNĘTRZNEGO i oczekiwać takich samych rezultatów. Ale są chwile, kiedy może to być przydatne ze względu na wydajność podczas korzystania z widoków.

Ostatnia uwaga - nie testowałem wpływu na wydajność w świetle powyższego, ale teoretycznie wydaje się, że powinieneś być w stanie bezpiecznie zastąpić WEJŚCIE WEWNĘTRZNE JOINEM ZEWNĘTRZNYM, jeśli dodasz również warunek <KLUCZ_KOPU> NIE JEST NULL do klauzuli where.

dbenham
źródło
5
Tak naprawdę natknąłem się na ten problem podczas tworzenia bardzo dynamicznych zapytań. Zostawiłem INNER JOIN, z którego korzystałem i nie pobierałem danych, a kiedy zmieniłem je na LEFT JOIN (z ciekawości ścinania), zapytanie faktycznie przebiegało szybciej.
Erik Philips,
1
EDYCJA - wyjaśniono warunki, które muszą istnieć, aby optymalizator usunął zewnętrzną połączoną tabelę z planu wykonania.
dbenham,
2
Jedno drobne wyjaśnienie do Twojej odpowiedzi: Gdy kolumna klucza obcego nie ma wartości zerowej, INNER JOIN i LEFT JOIN stają się semantycznie równoważne (tj. Sugerowana klauzula WHERE jest zbędna); jedyną różnicą byłby plan wykonania.
Douglas,
2
Choć pokazuje to na pozór banalny przykład, jest to niezwykle wnikliwa odpowiedź!
pbalaga
6
+1: Wydaje mi się, że natknąłem się na to w kilku zapytaniach, w których korzystałem z połączeń wewnętrznych z kilkoma bardzo dużymi tabelami. Sprzężenie wewnętrzne powodowało wyciek do tempdb w planie zapytań (zakładam z podanego powyżej powodu - a mój serwer nie ma pamięci RAM, aby utrzymać wszystko w pamięci). Przełączenie na lewe złączenie wyeliminowało wyciek do tempdb, w wyniku czego niektóre z moich 20-30 sekundowych zapytań działają teraz w ułamku sekundy. To bardzo ważna uwaga, ponieważ większość ludzi wydaje się przyjmować ogólne założenie, że połączenia wewnętrzne są szybsze.
fosfolit
23

Jeśli wszystko działa tak, jak nie powinno, ALE wszyscy wiemy, że wszystko nie działa tak, jak powinno, szczególnie jeśli chodzi o optymalizator zapytań, buforowanie planu zapytań i statystyki.

Najpierw zasugerowałbym przebudowanie indeksu i statystyk, a następnie wyczyszczenie pamięci podręcznej planu zapytań, aby upewnić się, że to nie popsuło. Jednak napotkałem problemy, nawet gdy to zrobiono.

Doświadczyłem niektórych przypadków, w których lewe połączenie było szybsze niż połączenie wewnętrzne.

Podstawowy powód jest następujący: jeśli masz dwie tabele i dołączasz do kolumny z indeksem (w obu tabelach). Sprzężenie wewnętrzne da ten sam wynik bez względu na to, czy zapętlisz wpisy w indeksie w tabeli 1 i dopasujesz z indeksem w tabeli 2, tak jakbyś zrobił odwrotnie: Zapętlić wpisy w indeksie w tabeli 2 i dopasować z indeksem w tabeli pierwszej. Problem polega na tym, że gdy masz mylące statystyki, optymalizator zapytań użyje statystyk indeksu, aby znaleźć tabelę z najmniej pasującymi pozycjami (na podstawie innych kryteriów). Jeśli masz dwie tabele z 1 milionem w każdej, w pierwszej tabeli masz 10 pasujących wierszy, aw drugiej tabeli 100 000 pasujących wierszy. Najlepszym sposobem byłoby wykonanie skanowania indeksu w tabeli pierwszej i dopasowanie 10 razy w tabeli drugiej. Odwrotnym byłoby skanowanie indeksu, które zapętla ponad 100 000 wierszy i próbuje dopasować 100 000 razy, a tylko 10 się powiedzie. Więc jeśli statystyki nie są poprawne, optymalizator może wybrać niewłaściwą tabelę i indeks, który ma być zapętlony.

Jeśli optymalizator zdecyduje się zoptymalizować lewe łączenie w kolejności, w jakiej jest zapisane, będzie działać lepiej niż łączenie wewnętrzne.

ALE, optymalizator może również zoptymalizować lewe łączenie suboptymalne jako lewe pół złączenie. Aby to zrobić, wybierz ten, który chcesz, możesz użyć podpowiedzi na temat wymuszania kolejności.

Kvasi
źródło
18

Wypróbuj oba zapytania (jedno z łączeniem wewnętrznym i lewym) z OPTION (FORCE ORDER)na końcu i opublikuj wyniki. OPTION (FORCE ORDER)jest wskazówką dotyczącą zapytania, która zmusza optymalizator do zbudowania planu wykonania przy użyciu kolejności łączenia podanej w zapytaniu.

Jeśli INNER JOINzacznie działać tak szybko jak LEFT JOINto, to dlatego, że:

  • W zapytaniu złożonym w całości przez INNER JOIN s kolejność łączenia nie ma znaczenia. Daje to optymalizatorowi kwerendę swobodę zamawiania połączeń według własnego uznania, więc problem może zależeć od optymalizatora.
  • W LEFT JOINprzypadku nie jest tak, ponieważ zmiana kolejności łączenia spowoduje zmianę wyników zapytania. Oznacza to, że silnik musi przestrzegać kolejności łączenia podanej w zapytaniu, która może być lepsza niż zoptymalizowana.

Nie wiem, czy to odpowiada na twoje pytanie, ale byłem kiedyś w projekcie, który zawierał bardzo złożone zapytania wykonujące obliczenia, które całkowicie zawiodły optymalizator. Mieliśmy przypadki, w których aFORCE ORDER skróciłoby czas wykonywania zapytania z 5 minut do 10 sekund.

Francisco Pires
źródło
9

Dokonałem szeregu porównań między lewymi złączami zewnętrznymi i wewnętrznymi i nie byłem w stanie znaleźć stałej różnicy. Istnieje wiele zmiennych. Pracuję nad bazą danych raportów z tysiącami tabel, wiele z dużą liczbą pól, wiele zmian w czasie (wersje dostawcy i lokalny przepływ pracy). Nie można utworzyć wszystkich kombinacji indeksów obejmujących, aby zaspokoić potrzeby tak szerokiej gamy zapytań i obsługiwać dane historyczne. Widziałem, że zapytania wewnętrzne zabijają wydajność serwera, ponieważ dwie duże (miliony do dziesiątków milionów wierszy) tabele są połączone wewnętrznie, oba pobierają dużą liczbę pól i nie istnieje indeks pokrycia.

Największy problem nie wydaje się jednak przemawiać w powyższych dyskusjach. Być może Twoja baza danych jest dobrze zaprojektowana z wyzwalaczami i dobrze zaprojektowanym przetwarzaniem transakcji, aby zapewnić dobre dane. Mój często ma wartości NULL tam, gdzie nie są oczekiwane. Tak, definicje tabel mogą wymuszać wartości zerowe, ale nie jest to opcja w moim środowisku.

Pytanie brzmi: czy projektujesz zapytanie tylko pod kątem szybkości, wyższego priorytetu dla przetwarzania transakcji, który uruchamia ten sam kod tysiące razy na minutę. Czy też dążysz do dokładności, jaką zapewni lewe połączenie zewnętrzne. Pamiętaj, że sprzężenia wewnętrzne muszą znajdować dopasowania po obu stronach, więc nieoczekiwany NULL nie tylko usunie dane z dwóch tabel, ale prawdopodobnie całe rzędy informacji. I dzieje się tak ładnie, bez komunikatów o błędach.

Możesz być bardzo szybki, ponieważ uzyskanie 90% potrzebnych danych i nie odkrywanie, że połączenia wewnętrzne po cichu usunęły informacje. Czasami połączenia wewnętrzne mogą być szybsze, ale nie sądzę, aby ktokolwiek przyjmował takie założenie, chyba że zapoznał się z planem wykonania. Szybkość jest ważna, ale ważniejsza jest dokładność.

JO
źródło
8

Prawdopodobnie problemy z wydajnością wynikają z liczby wykonywanych połączeń i tego, czy kolumny, do których dołączasz, mają indeksy, czy nie.

W najgorszym przypadku możesz łatwo wykonać 9 skanów całego stołu dla każdego połączenia.

eddiegroves
źródło
7

Połączenia zewnętrzne mogą oferować doskonałą wydajność, gdy są używane w widokach.

Załóżmy, że masz zapytanie obejmujące widok, a ten widok składa się z 10 tabel połączonych ze sobą. Załóżmy, że zapytanie używa tylko kolumn z 3 z tych 10 tabel.

Gdyby te 10 stołów zostało połączonych wewnętrznie , optymalizator zapytań musiałby połączyć je wszystkie, nawet jeśli samo zapytanie nie potrzebuje 7 z 10 tabel. Wynika to z faktu, że połączenia wewnętrzne same w sobie mogą filtrować dane, co czyni je niezbędnymi do obliczeń.

Gdyby te 10 tabel zostały połączone zewnętrznie sobą , wówczas optymalizator zapytań w rzeczywistości połączyłby tylko te, które były konieczne: 3 z 10 z nich w tym przypadku. Jest tak, ponieważ same sprzężenia nie filtrują już danych, a zatem nieużywane sprzężenia można pominąć.

Źródło: http://www.sqlservercentral.com/blogs/sql_coach/2010/07/29/poor-little-misunderstood-views/

MarredCheese
źródło
1
Twoje stwierdzenie o „przyłączeniu zewnętrznym” jest mylące i potencjalnie nieprawidłowe. Zewnętrzne oznacza, że ​​dane po drugiej stronie nie muszą istnieć - i jeśli nie zastąpią NULL. W szczególnych okolicznościach RDBMS może je „pominąć” (patrz wyżej odpowiedź dbenham). JEDNAK - zewnętrzny lub wewnętrzny może spowodować, że zapytanie zwróci całkowicie inne wyniki. WEWNĘTRZNE oznacza - podaje wyniki, dla których pozycja jest ZARÓWNO A I B. LEWA ZEWNĘTRZNA oznacza wszystkie A, a opcjonalnie B, jeśli istnieje. Pierwszy przypadek - dostajesz kilka rzędów, w drugim - WSZYSTKIE rzędy.
ripvlan,
1
@ripvlan Oczywiście połączenia zewnętrzne i wewnętrzne nie zawsze są wymienne. Pierwotne pytanie dotyczyło wydajności, co oznacza, że ​​mówimy o przypadkach, w których jedno z łączeń zwróci ten sam zestaw wyników.
MarredCheese,
1
Tak i - ZEWNĘTRZNY może powodować problem z wydajnością, ponieważ spowoduje zwrócenie wszystkich wierszy (więcej danych). Twoje założenie, że zapytania prowadzą do tego samego wyniku, jest słuszne - jednak nie jest to prawda w ogólnym przypadku i jest specyficzna dla każdego projektu db. A dla tych, którzy nie są w 100% zaznajomieni z relacyjną algebrą, mogą powodować ich smutek. Chodzi mi o to, aby zaoferować więcej wglądu osobom czytającym to i szukającym porady, i że LEWO / PRAWO nie rozwiąże problemu w magiczny sposób i może spowodować więcej problemów. Pozostała moc na poziomie 300 :-)
ripvlan 10.10.17
2

Znalazłem coś interesującego na serwerze SQL, gdy sprawdzam, czy połączenia wewnętrzne są szybsze niż połączenia lewe.

Jeśli nie uwzględnisz elementów lewej tabeli złączonej, w instrukcji select lewe złączenie będzie szybsze niż to samo zapytanie z łączeniem wewnętrznym.

Jeśli uwzględnisz lewą połączoną tabelę w instrukcji select, złączenie wewnętrzne z tym samym zapytaniem będzie równe lub szybsze niż lewe złączenie.

Buzzzzzzz
źródło
0

Z moich porównań wynika, że ​​mają dokładnie taki sam plan wykonania. Istnieją trzy scenariusze:

  1. Jeśli i kiedy zwracają te same wyniki, mają tę samą prędkość. Musimy jednak pamiętać, że nie są to te same zapytania i że LEFT JOIN zwróci więcej wyników (gdy niektóre warunki ON nie zostaną spełnione) - dlatego zwykle jest wolniejszy.

  2. Gdy główna tabela (pierwsza nie stała w planie wykonania) ma warunek ograniczający (GDZIE id =?), A odpowiadający jej warunek WŁĄCZONY ma wartość NULL, tabela „prawa” nie jest dołączana - wtedy LEFT JOIN jest szybszy.

  3. Jak omówiono w punkcie 1, zwykle INNER JOIN jest bardziej restrykcyjny i zwraca mniej wyników, a zatem jest szybszy.

Oba używają (tych samych) wskaźników.

Jiulin Teng
źródło