LEFT JOIN
není absolutně rychlejší než INNER JOIN
. Ve skutečnosti je pomalejší; podle definice vnější spojení (LEFT JOIN
nebo RIGHT JOIN
) musí udělat veškerou práci INNER JOIN
plus práce navíc s nulovým rozšířením výsledků. Očekávalo by se také, že vrátí více řádků, což dále prodlouží celkovou dobu provádění jednoduše kvůli větší velikosti sady výsledků.
(A to i v případě, že LEFT JOIN
byli rychlejší v konkrétním situace kvůli nějakému obtížně představitelnému souběhu faktorů, není funkčně ekvivalentní INNER JOIN
, takže nemůžete jednoduše nahradit všechny výskyty jednoho za druhý!)
Vaše problémy s výkonem s největší pravděpodobností leží jinde, například v tom, že nemáte správně indexovaný kandidátský klíč nebo cizí klíč. 9 stolů je poměrně hodně, takže zpomalení může být doslova téměř kdekoli. Pokud zveřejníte své schéma, možná vám budeme moci poskytnout další podrobnosti.
Upravit:
Když se nad tím zamyslím dále, napadá mě jedna okolnost, za které LEFT JOIN
může být rychlejší než INNER JOIN
, a to je, když:
- Některé tabulky jsou velmi malý (řekněme do 10 řádků);
- Tabulky nemají dostatečné indexy k pokrytí dotazu.
Zvažte tento příklad:
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
Pokud toto spustíte a zobrazíte plán provádění, uvidíte, že INNER JOIN
dotaz skutečně stojí více než LEFT JOIN
, protože splňuje dvě výše uvedená kritéria. Je to proto, že SQL Server chce provést hašovací shodu pro INNER JOIN
, ale dělá vnořené smyčky pro LEFT JOIN
; první je normálně mnohem rychleji, ale protože počet řádků je tak malý a neexistuje žádný index k použití, operace hašování se ukazuje jako nejdražší část dotazu.
Stejný efekt můžete vidět, když napíšete program ve svém oblíbeném programovacím jazyce, který provede velké množství vyhledávání v seznamu s 5 prvky, oproti hashovací tabulce s 5 prvky. Kvůli velikosti je verze hashovací tabulky ve skutečnosti pomalejší. Ale zvětšete to na 50 prvků nebo 5000 prvků a verze seznamu se zpomalí na procházení, protože je to O(N) vs. O(1) pro hashtable.
Ale změňte tento dotaz tak, aby byl na ID
místo Name
a uvidíte úplně jiný příběh. V takovém případě provede vnořené smyčky pro oba dotazy, ale INNER JOIN
verze je schopna nahradit jeden z clusterovaných indexových skenů hledáním – což znamená, že to bude doslova řádově rychlejší s velkým počtem řádků.
Takže závěr je víceméně to, co jsem zmínil o několik odstavců výše; téměř jistě se jedná o problém indexování nebo pokrytí indexu, případně v kombinaci s jednou nebo více velmi malými tabulkami. Toto jsou jediné okolnosti, za kterých SQL Server může někdy zvolte horší plán provedení pro INNER JOIN
než LEFT JOIN
.