sql >> Database teknologi >  >> RDS >> Sqlserver

INNER JOIN vs LEFT JOIN ydeevne i SQL Server

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 .



  1. Refaktorer fremmednøgle til felter

  2. Er et RID-opslag hurtigere end et nøgleopslag?

  3. Håndtering af MySQL-replikeringsproblemer ved hjælp af ClusterControl

  4. Brug tekstoutput fra en funktion som ny forespørgsel