sql >> Database >  >> RDS >> Sqlserver

INNER JOIN vs LEFT JOIN prestaties in SQL Server

EEN LEFT JOIN is absoluut niet sneller dan een INNER JOIN . In feite is het langzamer; per definitie een outer join (LEFT JOIN of RIGHT JOIN ) moet al het werk doen van een INNER JOIN plus het extra werk van het null-uitbreiden van de resultaten. Er wordt ook verwacht dat er meer rijen worden geretourneerd, waardoor de totale uitvoeringstijd verder toeneemt, simpelweg vanwege de grotere omvang van de resultatenset.

(En zelfs als een LEFT JOIN waren sneller in specifiek situaties als gevolg van een moeilijk voor te stellen samenloop van factoren, is het niet functioneel equivalent aan een INNER JOIN , dus je kunt niet zomaar alle instanties van de ene door de andere vervangen!)

Hoogstwaarschijnlijk liggen uw prestatieproblemen ergens anders, zoals het niet correct geïndexeerd hebben van een kandidaatsleutel of externe sleutel. 9 tafels is best veel om mee te doen, dus de vertraging kan letterlijk bijna overal zijn. Als je je schema post, kunnen we je misschien meer details geven.

Bewerken:

Als ik hier verder over nadenk, zou ik een omstandigheid kunnen bedenken waaronder een LEFT JOIN kan sneller zijn dan een INNER JOIN , en dat is wanneer:

  • Sommige tabellen zijn erg klein (zeg onder de 10 rijen);
  • De tabellen hebben niet voldoende indexen om de zoekopdracht te dekken.

Beschouw dit voorbeeld:

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

Als u dit uitvoert en het uitvoeringsplan bekijkt, ziet u dat de INNER JOIN zoekopdracht kost inderdaad meer dan de LEFT JOIN , omdat het voldoet aan de twee bovenstaande criteria. Het is omdat SQL Server een hash-overeenkomst wil doen voor de INNER JOIN , maar doet geneste lussen voor de LEFT JOIN; de eerste is normaal veel sneller, maar omdat het aantal rijen zo klein is en er is geen index om te gebruiken, de hash-bewerking blijkt het duurste deel van de zoekopdracht te zijn.

U kunt hetzelfde effect zien door een programma in uw favoriete programmeertaal te schrijven om een ​​groot aantal zoekopdrachten uit te voeren op een lijst met 5 elementen, versus een hashtabel met 5 elementen. Vanwege de grootte is de hashtabelversie eigenlijk langzamer. Maar verhoog het tot 50 elementen, of 5000 elementen, en de lijstversie vertraagt ​​tot een crawl, omdat het O(N) versus O(1) is voor de hashtabel.

Maar verander deze zoekopdracht zodat deze op de ID staat kolom in plaats van Name en je krijgt een heel ander verhaal te zien. In dat geval doet het geneste lussen voor beide zoekopdrachten, maar de INNER JOIN versie kan een van de geclusterde indexscans vervangen door een seek - wat betekent dat dit letterlijk een orde van grootte zal zijn sneller met een groot aantal rijen.

Dus de conclusie is min of meer wat ik enkele paragrafen hierboven noemde; dit is vrijwel zeker een indexerings- of indexdekkingsprobleem, mogelijk gecombineerd met een of meer zeer kleine tabellen. Dat zijn de enige omstandigheden waaronder SQL Server mogelijk kies soms een slechter uitvoeringsplan voor een INNER JOIN dan een LEFT JOIN .



  1. Detecteer dubbele items in recursieve CTE

  2. PostgreSQL:welk gegevenstype moet worden gebruikt voor valuta?

  3. Hoe te repareren Ora-01427 single-rij subquery retourneert meer dan één rij in select?

  4. Dynamische draaikolommen in SQL Server