Twój pogląd, że powinni wykonywać tę samą pracę, nie jest prawdziwy. Wyobraź sobie ten testowy zestaw danych:
T1
ID
----
1
2
3
4
5
T2
ID
---
1
1
1
2
2
3
DDL
CREATE TABLE dbo.T1 (ID INT NOT NULL);
INSERT dbo.T1 (ID) VALUES (1), (2), (3), (4), (5);
CREATE TABLE dbo.T2 (ID INT NOT NULL);
INSERT dbo.T2 (ID) VALUES (1), (1), (1), (2), (2), (3);
SELECT *
FROM dbo.T1
WHERE T1.ID IN (SELECT T2.ID FROM dbo.T2);
SELECT T1.*
FROM dbo.T1
INNER JOIN dbo.T2
ON T1.ID = T2.ID;
Wyniki
ID
---
1
2
3
ID
---
1
1
1
2
2
3
Twoje wyniki są takie same tylko wtedy, gdy kolumna, w której szukasz, jest unikalna.
CREATE TABLE dbo.T1 (ID INT NOT NULL);
INSERT dbo.T1 (ID) VALUES (1), (2), (3), (4), (5);
CREATE TABLE dbo.T2 (ID INT NOT NULL);
INSERT dbo.T2 (ID) VALUES (1), (2), (3);
SELECT *
FROM dbo.T1
WHERE T1.ID IN (SELECT T2.ID FROM dbo.T2);
SELECT T1.*
FROM dbo.T1
INNER JOIN dbo.T2
ON T1.ID = T2.ID;
Mimo że wyniki są takie same, plan wykonania nie. Pierwsze zapytanie używające IN
potrafi użyć antysemi join, co oznacza, że wie, że dane w t2 nie są potrzebne, więc gdy tylko znajdzie pojedyncze dopasowanie, może przestać szukać dalszych dopasowań.
Jeśli ograniczysz swoją drugą tabelę tak, aby zawierała tylko unikalne wartości, zobaczysz ten sam plan:
CREATE TABLE dbo.T1 (ID INT NOT NULL PRIMARY KEY);
INSERT dbo.T1 (ID) VALUES (1), (2), (3), (4), (5);
CREATE TABLE dbo.T2 (ID INT NOT NULL PRIMARY KEY);
INSERT dbo.T2 (ID) VALUES (1), (2), (3);
SELECT *
FROM dbo.T1
WHERE T1.ID IN (SELECT T2.ID FROM dbo.T2);
SELECT T1.*
FROM dbo.T1
INNER JOIN dbo.T2
ON T1.ID = T2.ID;
Podsumowując, te dwa zapytania nie zawsze przyniosą te same wyniki i nie zawsze będą miały ten sam plan. To naprawdę zależy od twoich indeksów i szerokości twoich danych/zapytań.