Актуализация:
Тази статия в моя блог обобщава както моя отговор, така и моите коментари към други отговори и показва действителни планове за изпълнение:
SELECT *
FROM a
WHERE a.c IN (SELECT d FROM b)
SELECT a.*
FROM a
JOIN b
ON a.c = b.d
Тези заявки не са еквивалентни. Те могат да дадат различни резултати, ако вашата таблица b
не е запазен ключ (т.е. стойностите на b.d
не са уникални).
Еквивалентът на първата заявка е следният:
SELECT a.*
FROM a
JOIN (
SELECT DISTINCT d
FROM b
) bo
ON a.c = bo.d
Ако b.d
е UNIQUE
и маркиран като такъв (с UNIQUE INDEX
или UNIQUE CONSTRAINT
), тогава тези заявки са идентични и най-вероятно ще използват идентични планове, тъй като SQL Server
е достатъчно умен, за да вземе това предвид.
SQL Server
може да използва един от следните методи за изпълнение на тази заявка:
-
Ако има индекс на
a.c
,d
еUNIQUE
иb
е относително малък в сравнение сa
, тогава условието се разпространява в подзаявката и обикновенияINNER JOIN
се използва (сb
водещ) -
Ако има индекс на
b.d
иd
не еUNIQUE
, тогава условието също се разпространява иLEFT SEMI JOIN
се използва. Може да се използва и за горното състояние. -
Ако има индекс и на двата
b.d
иa.c
и те са големи, тогаваMERGE SEMI JOIN
се използва -
Ако няма индекс на която и да е таблица, тогава се изгражда хеш таблица върху
b
иHASH SEMI JOIN
се използва.
Нито от тези методи преоценява цялата подзаявка всеки път.
Вижте този запис в моя блог за повече подробности как работи това:
Има връзки за всички RDBMS
е от голямата четворка.