En LEFT JOIN
er absolut ikke hurtigere end en INNER JOIN
. Faktisk er det langsommere; per definition en ydre forbindelse (LEFT JOIN
eller RIGHT JOIN
) skal udføre alt arbejdet med en INNER JOIN
plus det ekstra arbejde med at nul-forlænge resultaterne. Det ville også forventes at returnere flere rækker, hvilket yderligere øger den samlede udførelsestid blot på grund af den større størrelse af resultatsættet.
(Og selv hvis en LEFT JOIN
var hurtigere i specifik situationer på grund af en eller anden svær at forestille sig sammenblanding af faktorer, er det funktionelt ikke ækvivalent med en INNER JOIN
, så du kan ikke bare erstatte alle forekomster af den ene med den anden!)
Højst sandsynligt ligger dine præstationsproblemer andre steder, såsom ikke at have en kandidatnøgle eller fremmednøgle indekseret korrekt. 9 borde er ret meget at deltage i, så afmatningen kunne bogstaveligt talt være næsten hvor som helst. Hvis du sender dit skema, kan vi muligvis give flere detaljer.
Rediger:
Når jeg reflekterer videre over dette, kunne jeg tænke på én omstændighed, hvorunder en LEFT JOIN
kan være hurtigere end en INNER JOIN
, og det er når:
- Nogle af tabellerne er meget lille (f.eks. under 10 rækker);
- Tabellerne har ikke tilstrækkelige indekser til at dække forespørgslen.
Overvej dette eksempel:
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
Hvis du kører dette og ser udførelsesplanen, vil du se, at INNER JOIN
forespørgslen koster faktisk mere end LEFT JOIN
, fordi den opfylder de to ovenstående kriterier. Det er fordi SQL Server ønsker at lave et hash-match for INNER JOIN
, men laver indlejrede loops for LEFT JOIN
; førstnævnte er normalt meget hurtigere, men da antallet af rækker er så lille og der er intet indeks at bruge, hashing-operationen viser sig at være den dyreste del af forespørgslen.
Du kan se den samme effekt ved at skrive et program på dit foretrukne programmeringssprog for at udføre et stort antal opslag på en liste med 5 elementer, kontra en hash-tabel med 5 elementer. På grund af størrelsen er hash-tabelversionen faktisk langsommere. Men forøg den til 50 elementer eller 5000 elementer, og listeversionen bliver langsommere til en gennemgang, fordi den er O(N) vs. O(1) for hashtabellen.
Men skift denne forespørgsel til at være på ID
kolonne i stedet for Name
og du vil se en meget anderledes historie. I så fald udfører den indlejrede løkker for begge forespørgsler, men INNER JOIN
version er i stand til at erstatte en af de klyngede indeksscanninger med en søgning - hvilket betyder, at dette bogstaveligt talt vil være en størrelsesorden hurtigere med et stort antal rækker.
Så konklusionen er mere eller mindre hvad jeg nævnte flere afsnit ovenfor; dette er næsten helt sikkert et indekserings- eller indeksdækningsproblem, muligvis kombineret med en eller flere meget små tabeller. Det er de eneste omstændigheder, hvorunder SQL Server kan vælger nogle gange en dårligere udførelsesplan for en INNER JOIN
end en LEFT JOIN
.