Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Cách hiệu quả nhất để CHỌN hàng nơi ID TỒN TẠI trong bảng thứ hai

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 ..

  1. Một tập hợp kết quả truy vấn con rất lớn (100000 hàng)
  2. Các hàng trùng lặp
  3. Hàng rỗng

Đối với tất cả các trường hợp trên, cả INEXISTS đượ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.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sử dụng SMO, vẫn không đi được ... ConnectionContext.ExecuteNonQuery (script) không thể hiểu GO

  2. Hợp nhất nhiều bản ghi thành một hàng trong bảng

  3. Làm cách nào để lấy số thứ tự tiếp theo trong Sql Server Express bằng Entity Framework?

  4. ReportViewer 11 (2012) Visual Studio 2010

  5. SQL Server 2008 - Trên Kích hoạt Chèn / Cập nhật sao chép các giá trị sang một bảng khác?