Tôi đang cố gắng tạo một kế hoạch truy vấn mẫu để cho thấy tại sao UNIONing hai tập kết quả có thể tốt hơn so với sử dụng OR trong mệnh đề THAM GIA. Một kế hoạch truy vấn tôi đã viết đã làm tôi bối rối. Tôi đang sử dụng cơ sở dữ liệu StackOverflow với chỉ mục không bao gồm trên Users.Reputing.
CREATE NONCLUSTERED INDEX IX_NC_REPUTATION ON dbo.USERS(Reputation)
SELECT DISTINCT Users.Id
FROM dbo.Users
INNER JOIN dbo.Posts
ON Users.Id = Posts.OwnerUserId
OR Users.Id = Posts.LastEditorUserId
WHERE Users.Reputation = 5
Gói truy vấn có tại https://www.brentozar.com/pastetheplan/?id=BkpZU1MZE , thời lượng truy vấn đối với tôi là 4:37 phút, trả về 26612 hàng.
Tôi chưa từng thấy kiểu quét liên tục này được tạo từ một bảng hiện có trước đây - Tôi không quen tại sao lại có quét liên tục cho mỗi hàng, khi quét thường xuyên được sử dụng cho một hàng được người dùng nhập vào ví dụ CHỌN GETDATE (). Tại sao nó được sử dụng ở đây? Tôi thực sự sẽ đánh giá cao một số hướng dẫn trong việc đọc kế hoạch truy vấn này.
Nếu tôi tách HOẶC đó thành UNION, nó sẽ tạo ra một gói tiêu chuẩn chạy trong 12 giây với cùng 26612 hàng được trả về.
SELECT Users.Id
FROM dbo.Users
INNER JOIN dbo.Posts
ON Users.Id = Posts.OwnerUserId
WHERE Users.Reputation = 5
UNION
SELECT Users.Id
FROM dbo.Users
INNER JOIN dbo.Posts
ON Users.Id = Posts.LastEditorUserId
WHERE Users.Reputation = 5
Tôi giải thích kế hoạch này là làm điều này:
- Nhận tất cả 41782500 hàng từ Bài viết (số lượng hàng thực tế khớp với quét CI trên Bài đăng)
- Đối với mỗi 41782500 hàng trong Bài viết:
- Sản xuất vô hướng:
- Expr1005: Chủ sở hữuUserId
- Expr1006: Chủ sở hữuUserId
- Expr1004: Giá trị tĩnh 62
- Expr1008: LastEditorUserId
- Expr1009: LastEditorUserId
- Expr1007: Giá trị tĩnh 62
- Trong phần kết hợp:
- Exp1010: Nếu Expr1005 (Chủ sở hữuUserId) không rỗng, hãy sử dụng Expr1008 (LastEditorUserID) khác
- Expr1011: Nếu Expr1006 (Chủ sở hữuUserId) không rỗng, hãy sử dụng điều đó, sử dụng Expr1009 (LastEditorUserId)
- Expr1012: Nếu Expr1004 (62) là null, hãy sử dụng Expr1007 (62)
- Trong vô hướng tính toán: Tôi không biết ampersand làm gì.
- Expr1013: 4 [và?] 62 (Expr1012) = 4 và Chủ sở hữuUserId là NULL (NULL = Expr1010)
- Expr1014: 4 [và?] 62 (Expr1012)
- Expr1015: 16 và 62 (Expr1012)
- Theo thứ tự Sắp xếp theo:
- Expr1013 Desc
- Expr1014
- Expr1010
- Expr1015 Desc
- Trong Khoảng thời gian hợp nhất, nó đã loại bỏ Expr1013 và Expr1015 (đây là các đầu vào nhưng không phải là đầu ra)
- Trong Chỉ mục tìm kiếm bên dưới các vòng lặp lồng nhau, nó sử dụng Expr1010 và Expr1011 làm vị ngữ tìm kiếm, nhưng tôi không hiểu làm thế nào nó có quyền truy cập vào các vòng lặp này khi nó không thực hiện nối vòng lặp lồng nhau từ IX_NC_REPUTATION đến cây con có chứa Expr1010 và Expr1011 .
- Các vòng lặp Nested Loops chỉ trả về các Users.ID có khớp trong phần phụ trước đó. Do đẩy xuống vị ngữ, tất cả các hàng được trả về từ chỉ mục tìm kiếm trên IX_NC_REPUTATION được trả về.
- Các vòng lặp lồng nhau cuối cùng tham gia: Đối với mỗi bản ghi Bài đăng, hãy xuất Users.Id nơi tìm thấy kết quả khớp trong tập dữ liệu bên dưới.
SELECT Users.Id FROM dbo.Users WHERE Users.Reputation = 5 AND EXISTS (SELECT 1 FROM dbo.Posts WHERE Users.Id IN (Posts.OwnerUserId, Posts.LastEditorUserId) ) ;
SELECT Users.Id FROM dbo.Users WHERE Users.Reputation = 5 AND ( EXISTS (SELECT 1 FROM dbo.Posts WHERE Users.Id = Posts.OwnerUserId) OR EXISTS (SELECT 1 FROM dbo.Posts WHERE Users.Id = Posts.LastEditorUserId) ) ;