sql >> Databasteknik >  >> RDS >> Sqlserver

INNER JOIN vs LEFT JOIN prestanda i SQL Server

En LEFT JOIN är absolut inte snabbare än en INNER JOIN . I själva verket är det långsammare; per definition en yttre koppling (LEFT JOIN eller RIGHT JOIN ) måste göra allt arbete med en INNER JOIN plus det extra arbetet med att nollförlänga resultaten. Det skulle också förväntas returnera fler rader, vilket ytterligare ökar den totala exekveringstiden helt enkelt på grund av den större storleken på resultatuppsättningen.

(Och även om en LEFT JOIN var snabbare i specifikt situationer på grund av något svårföreställt sammanflöde av faktorer, är det inte funktionellt likvärdigt med en INNER JOIN , så du kan inte helt enkelt byta ut alla instanser av den ena med den andra!)

Troligtvis ligger dina prestandaproblem någon annanstans, som att inte ha en kandidatnyckel eller främmande nyckel indexerad ordentligt. 9 bord är ganska mycket att gå med så nedgången kan bokstavligen vara nästan var som helst. Om du lägger upp ditt schema kanske vi kan ge mer information.

Redigera:

När jag reflekterar vidare över detta, skulle jag kunna tänka mig en omständighet under vilken en LEFT JOIN kan vara snabbare än en INNER JOIN , och det är då:

  • En del av tabellerna är mycket liten (säg under 10 rader);
  • Tabellerna har inte tillräckligt med index för att täcka frågan.

Tänk på det här exemplet:

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

Om du kör detta och tittar på exekveringsplanen ser du att INNER JOIN frågan kostar verkligen mer än LEFT JOIN , eftersom den uppfyller de två kriterierna ovan. Det beror på att SQL Server vill göra en hash-matchning för INNER JOIN , men gör kapslade loopar för LEFT JOIN; den förra är normalt mycket snabbare, men eftersom antalet rader är så små och det finns inget index att använda, hashoperationen visar sig vara den dyraste delen av frågan.

Du kan se samma effekt genom att skriva ett program på ditt favoritspråk för att utföra ett stort antal uppslagningar på en lista med 5 element, jämfört med en hashtabell med 5 element. På grund av storleken är hashtabellversionen faktiskt långsammare. Men öka den till 50 element, eller 5000 element, och listversionen saktar ner till en genomsökning, eftersom det är O(N) mot O(1) för hashtabellen.

Men ändra denna fråga till att vara på ID kolumn istället för Name och du kommer att se en helt annan historia. I så fall gör den kapslade loopar för båda frågorna, men INNER JOIN versionen kan ersätta en av de klustrade indexskanningarna med en sökning - vilket betyder att detta bokstavligen kommer att vara en storleksordning snabbare med ett stort antal rader.

Så slutsatsen är mer eller mindre vad jag nämnde flera stycken ovan; detta är nästan säkert ett indexerings- eller indextäckningsproblem, möjligen i kombination med en eller flera mycket små tabeller. Det är de enda omständigheterna under vilka SQL Server kan ibland väljer en sämre exekveringsplan för en INNER JOIN än en LEFT JOIN .



  1. Hur kan jag komma runt MySQL Errcode 13 med SELECT INTO OUTFILE?

  2. PÅ DUBLIKATKEY + AUTO ÖKNING utfärda mysql

  3. SQL Server:dynamisk pivot över 5 kolumner

  4. Kontrollera om RPC Out är aktiverat på en länkad server