Tôi đã có một truy vấn như sau:
DELETE FROM tblFEStatsBrowsers WHERE BrowserID NOT IN (
SELECT DISTINCT BrowserID FROM tblFEStatsPaperHits WITH (NOLOCK) WHERE BrowserID IS NOT NULL
)
tblFEStatsBỏ đã có 553 hàng.
tblFEStatsPaperHits đã có 47.974.301 hàng.
tblFEStatsBỏ:
CREATE TABLE [dbo].[tblFEStatsBrowsers](
[BrowserID] [smallint] IDENTITY(1,1) NOT NULL,
[Browser] [varchar](50) NOT NULL,
[Name] [varchar](40) NOT NULL,
[Version] [varchar](10) NOT NULL,
CONSTRAINT [PK_tblFEStatsBrowsers] PRIMARY KEY CLUSTERED ([BrowserID] ASC)
)
tblFEStatsPaperHits:
CREATE TABLE [dbo].[tblFEStatsPaperHits](
[PaperID] [int] NOT NULL,
[Created] [smalldatetime] NOT NULL,
[IP] [binary](4) NULL,
[PlatformID] [tinyint] NULL,
[BrowserID] [smallint] NULL,
[ReferrerID] [int] NULL,
[UserLanguage] [char](2) NULL
)
Có một chỉ mục được nhóm trên tblFEStatsPaperHits không bao gồm BrowserID. Do đó, việc thực hiện truy vấn bên trong sẽ yêu cầu quét toàn bộ bảng tblFEStatsPaperHits - hoàn toàn ổn.
Hiện tại, quá trình quét toàn bộ được thực hiện cho từng hàng trong tblFEStatsBrowsers, nghĩa là tôi đã có 553 lần quét toàn bộ bảng của tblFEStatsPaperHits.
Viết lại thành EXISTS WHERE không thay đổi kế hoạch:
DELETE FROM tblFEStatsBrowsers WHERE NOT EXISTS (
SELECT * FROM tblFEStatsPaperHits WITH (NOLOCK) WHERE BrowserID = tblFEStatsBrowsers.BrowserID
)
Tuy nhiên, như được đề xuất bởi Adam Machanic, việc thêm tùy chọn HASH THAM GIA sẽ dẫn đến kế hoạch thực hiện tối ưu (chỉ một lần quét tblFEStatsPaperHits):
DELETE FROM tblFEStatsBrowsers WHERE NOT EXISTS (
SELECT * FROM tblFEStatsPaperHits WITH (NOLOCK) WHERE BrowserID = tblFEStatsBrowsers.BrowserID
) OPTION (HASH JOIN)
Bây giờ đây không phải là câu hỏi về cách khắc phục vấn đề này - tôi có thể sử dụng TÙY CHỌN (HASH THAM GIA) hoặc tạo bảng tạm thời theo cách thủ công. Tôi tự hỏi tại sao trình tối ưu hóa truy vấn sẽ sử dụng gói mà nó hiện đang làm.
Vì QO không có bất kỳ số liệu thống kê nào trên cột BrowserID, tôi đoán rằng nó giả định là tồi tệ nhất - 50 triệu giá trị riêng biệt, do đó đòi hỏi một bàn làm việc trong bộ nhớ / tempdb khá lớn. Như vậy, cách an toàn nhất là thực hiện quét cho từng hàng trong tblFEStatsBrowsers. Không có mối quan hệ khóa ngoài giữa các cột BrowserID trong hai bảng, vì vậy QO không thể khấu trừ bất kỳ thông tin nào từ tblFEStatsBrowsers.
Đây có phải là, đơn giản như nó nghe, lý do?
Cập nhật 1
Để đưa ra một vài số liệu thống kê: TÙY CHỌN (HASH THAM GIA):
208.711 lần đọc logic (12 lần quét)
TÙY CHỌN (LOOP THAM GIA, NHÓM HASH):
11.008.698 lần đọc logic (~ quét trên BrowserID (339))
Không có tùy chọn:
11.008.775 lần đọc logic (~ quét trên BrowserID (339))
Cập nhật 2
câu trả lời tuyệt vời, tất cả các bạn - cảm ơn! Khó khăn để chọn chỉ một. Mặc dù Martin là người đầu tiên và Remus cung cấp một giải pháp tuyệt vời, tôi phải đưa nó cho Kiwi vì đã chú ý đến các chi tiết :)