IN() и EXISTS() в SqlServer 2005 (или вообще в любой СУБД)

Я пытаюсь выяснить, что быстрее, предложение типа WHERE IN (SELECT 1 FROM MyTable) "или предложение типа WHERE EXISTS (SELECT 1 FROM MyTable).

Позвольте использовать запрос из документации SqlServer:

SELECT * FROM Orders 
WHERE ShipRegion = 'WA' AND EXISTS (
    SELECT EmployeeID FROM Employees AS Emp 
    WHERE Emp.EmployeeID = Orders.EmployeeID)

или

SELECT * FROM Order
WHERE ShipRegion = 'WA' AND EmployeeID IN (
    SELECT EmployeeID FROM Employees AS Emp 
    WHERE Emp.EmployeeID = Orders.EmployeeID)

Я хотел бы узнать ответ, если у кого-то это есть, но мне бы очень хотелось узнать, как его проверить для себя в SqlServer 2005. (Я - noob на SqlServer.)

Спасибо!

Ответ 1

Чтобы убедиться, вы можете: сравнить реальные затраты на выполнение, запустить

SET STATISTICS IO ON
SET STATISTICS TIME ON

затем запустите оба запроса

Также сравните планы выполнения, выделите оба запроса и нажмите Ctrl + L, и вы увидите планы. Скорее всего, вы увидите идентичные планы.

Ответ 2

Использование INNER JOIN будет быстрее, чем подзапрос:

SELECT * 
  FROM Order o
 INNER JOIN Employees e ON o.EmployeeID = e.EmployeeID
 WHERE ShipRegion = 'WA'

Или с конкретными критериями:

 SELECT * 
  FROM Order o
 INNER JOIN Employees e ON o.EmployeeID = e.EmployeeID
 WHERE ShipRegion = 'WA'
   AND e.EmployeeID = 42

Ответ 3

Вы также можете удалить предложение WHERE в случае IN:

SELECT * FROM Orders
WHERE ShipRegion = 'WA' AND EmployeeID IN (SELECT EmployeeID FROM Employees)

Оптимизатор запросов должен иметь возможность создавать идентичный план выполнения для обоих запросов. Я бы выбрал тот, который был бы более читабельным.

Ответ 4

Подпроцесс sql, хотя и идентичный, не даст вам ответ, который вы ищете, поскольку он связан со связью и может быть изменен в JOIN.

В общем случае EXISTS() должен быть быстрее, так как он дает результат, не найдя больше отношений, если он найдет первую строку, тогда как IN() все еще должен найти последующие строки до тех пор, пока они не закончатся.

поэтому

SELECT * FROM Orders 
WHERE ShipRegion = 'WA' AND EXISTS (
    SELECT 'x' FROM Employees AS Emp 
    WHERE Emp.EmployeeID = 42)

должен заканчиваться до

SELECT * FROM Order
WHERE ShipRegion = 'WA' AND EmployeeID IN (
    SELECT EmployeeID FROM Employees AS Emp 
    WHERE Emp.EmployeeID = 42)