Tóm tắt:
Tôi đã chạy mỗi truy vấn 10 lần mỗi truy vấn bằng cách sử dụng tập dữ liệu thử nghiệm bên dưới ..
- Một tập hợp kết quả truy vấn con rất lớn (100000 hàng)
- Các hàng trùng lặp
- Hàng rỗng
Đối với tất cả các trường hợp trên, cả IN
và EXISTS
được thực hiện theo cách giống hệt nhau.
Một số thông tin về cơ sở dữ liệu Performance V3 được sử dụng để thử nghiệm. 1200 khách hàng có 1000000 đơn đặt hàng, vì vậy mỗi khách hàng được sao chép ngẫu nhiên (trong phạm vi từ 10 đến 100) trong bảng đơn đặt hàng.
Chi phí thực hiện, Thời gian:
Dưới đây là ảnh chụp màn hình của cả hai truy vấn đang chạy. Quan sát chi phí tương đối của từng truy vấn.
Chi phí bộ nhớ: Cấp bộ nhớ
cho hai truy vấn cũng giống nhau..Tôi buộc MDOP 1 để không làm tràn chúng sang TEMPDB ..
Thời gian CPU, Số lần đọc:
Đối với Tồn tại:
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Customers'. Scan count 1, logical reads 109, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Orders'. Scan count 1, logical reads 3855, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
SQL Server Execution Times:
CPU time = 469 ms, elapsed time = 595 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
Đối với IN:
(20000 row(s) affected)
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Customers'. Scan count 1, logical reads 109, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Orders'. Scan count 1, logical reads 3855, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
SQL Server Execution Times:
CPU time = 547 ms, elapsed time = 669 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
Trong mỗi trường hợp, trình tối ưu hóa đủ thông minh để sắp xếp lại các truy vấn.
Tôi có xu hướng sử dụng EXISTS
chỉ mặc dù (ý kiến của tôi). Một ca sử dụng để sử dụng EXISTS
là khi bạn không muốn trả về tập hợp kết quả bảng thứ hai.
Cập nhật theo truy vấn từ Martin Smith:
Tôi đã chạy các truy vấn dưới đây để tìm cách hiệu quả nhất để lấy các hàng từ bảng đầu tiên có tham chiếu tồn tại trong bảng thứ hai.
SELECT DISTINCT c.*
FROM Customers c
JOIN Orders o ON o.custid = c.custid
SELECT c.*
FROM Customers c
INNER JOIN (SELECT DISTINCT custid FROM Orders) AS o ON o.custid = c.custid
SELECT *
FROM Customers C
WHERE EXISTS(SELECT 1 FROM Orders o WHERE o.custid = c.custid)
SELECT *
FROM Customers c
WHERE custid IN (SELECT custid FROM Orders)
Tất cả các truy vấn trên đều có chung chi phí ngoại trừ INNER JOIN
thứ 2 , Lập kế hoạch giống nhau cho phần còn lại.
Cấp bộ nhớ:
Truy vấn này
SELECT DISTINCT c.*
FROM Customers c
JOIN Orders o ON o.custid = c.custid
yêu cầu cấp bộ nhớ của
Truy vấn này
SELECT c.*
FROM Customers c
INNER JOIN (SELECT DISTINCT custid FROM Orders) AS o ON o.custid = c.custid
yêu cầu cấp bộ nhớ của ..
Thời gian CPU, Số lần đọc:
Đối với Truy vấn:
SELECT DISTINCT c.*
FROM Customers c
JOIN Orders o ON o.custid = c.custid
(20000 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Workfile'. Scan count 48, logical reads 1344, physical reads 96, read-ahead reads 1248, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Orders'. Scan count 5, logical reads 3929, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Customers'. Scan count 5, logical reads 322, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 1453 ms, elapsed time = 781 ms.
Đối với Truy vấn:
SELECT c.*
FROM Customers c
INNER JOIN (SELECT DISTINCT custid FROM Orders) AS o ON o.custid = c.custid
(20000 row(s) affected)
Table 'Customers'. Scan count 5, logical reads 322, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Orders'. Scan count 5, logical reads 3929, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 1499 ms, elapsed time = 403 ms.