Tôi không nghĩ nó có liên quan gì đến việc chậm kinh khủng; nó phải làm với khả năng không chính xác. Ví dụ: được cung cấp dữ liệu sau - các đơn đặt hàng có thể được đặt bởi một khách hàng cá nhân hoặc đối tác B2B:
DECLARE @Customers TABLE(CustomerID INT);
INSERT @Customers VALUES(1),(2);
DECLARE @Orders TABLE(OrderID INT, CustomerID INT, CompanyID INT);
INSERT @Orders VALUES(10,1,NULL),(11,NULL,5);
Hãy nói rằng tôi muốn tìm tất cả các khách hàng chưa bao giờ đặt hàng. Đưa ra dữ liệu, chỉ có một: khách hàng số 2. Dưới đây là ba cách tôi có thể viết về một truy vấn để tìm thông tin đó (có những cách khác):
SELECT [NOT IN] = CustomerID FROM @Customers
WHERE CustomerID NOT IN (SELECT CustomerID FROM @Orders);
SELECT [NOT EXISTS] = CustomerID FROM @Customers AS c
WHERE NOT EXISTS (SELECT 1 FROM @Orders AS o
WHERE o.CustomerID = c.CustomerID);
SELECT [EXCEPT] = CustomerID FROM @Customers
EXCEPT SELECT CustomerID FROM @Orders;
Các kết quả:
NOT IN
------
-- <-- no results. Is that what you expected?
NOT EXISTS
----------
2
EXCEPT
------
2
Bây giờ, có một số vấn đề hiệu suất là tốt, và tôi nói về chúng trong bài viết trên blog này . Tùy thuộc vào dữ liệu và chỉ mục, NOT EXISTS
thường sẽ tốt hơn NOT IN
và tôi không biết liệu nó có thể hoạt động kém hơn không. Bạn cũng nên lưu ý rằng EXCEPT
có thể giới thiệu một hoạt động sắp xếp riêng biệt, do đó bạn có thể kết thúc với dữ liệu khác nhau (một lần nữa, tùy thuộc vào nguồn). Và rằng LEFT OUTER JOIN ... WHERE right.column IS NULL
mô hình phổ biến luôn luôn là biểu diễn tồi tệ nhất.
Martin Smith cũng có rất nhiều thông tin hỗ trợ tốt trong câu trả lời của mình về SO .
IN
/NOT IN
sẽ luôn được thực hiện với các vòng lặp lồng nhau. Và tôi không biết những gìstops SQL Server from creating a ‘plan’
được cho là có nghĩa.