Hãy xem xét truy vấn sau đây chỉ chèn các hàng từ bảng nguồn nếu chúng chưa có trong bảng đích:
INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT maybe_new_rows.ID
FROM dbo.A_HEAP_OF_MOSTLY_NEW_ROWS maybe_new_rows
WHERE NOT EXISTS (
SELECT 1
FROM dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR halloween
WHERE maybe_new_rows.ID = halloween.ID
)
OPTION (MAXDOP 1, QUERYTRACEON 7470);
Một hình dạng kế hoạch có thể bao gồm một liên kết hợp nhất và một ống chỉ háo hức. Toán tử spool háo hức có mặt để giải quyết vấn đề Halloween :
Trên máy của tôi, đoạn mã trên thực thi trong khoảng 6900 ms. Mã repro để tạo các bảng được bao gồm ở dưới cùng của câu hỏi. Nếu tôi không hài lòng với hiệu suất, tôi có thể thử tải các hàng được chèn vào bảng tạm thời thay vì dựa vào bộ đệm háo hức. Đây là một triển khai có thể:
DROP TABLE IF EXISTS #CONSULTANT_RECOMMENDED_TEMP_TABLE;
CREATE TABLE #CONSULTANT_RECOMMENDED_TEMP_TABLE (
ID BIGINT,
PRIMARY KEY (ID)
);
INSERT INTO #CONSULTANT_RECOMMENDED_TEMP_TABLE WITH (TABLOCK)
SELECT maybe_new_rows.ID
FROM dbo.A_HEAP_OF_MOSTLY_NEW_ROWS maybe_new_rows
WHERE NOT EXISTS (
SELECT 1
FROM dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR halloween
WHERE maybe_new_rows.ID = halloween.ID
)
OPTION (MAXDOP 1, QUERYTRACEON 7470);
INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT new_rows.ID
FROM #CONSULTANT_RECOMMENDED_TEMP_TABLE new_rows
OPTION (MAXDOP 1);
Mã mới thực thi trong khoảng 4400 ms. Tôi có thể nhận các kế hoạch thực tế và sử dụng Thống kê thời gian thực tế ™ để kiểm tra xem thời gian được sử dụng ở cấp độ nhà điều hành. Lưu ý rằng việc yêu cầu một kế hoạch thực tế sẽ thêm chi phí đáng kể cho các truy vấn này để tổng số sẽ không khớp với kết quả trước đó.
╔═════════════╦═════════════╦══════════════╗
║ operator ║ first query ║ second query ║
╠═════════════╬═════════════╬══════════════╣
║ big scan ║ 1771 ║ 1744 ║
║ little scan ║ 163 ║ 166 ║
║ sort ║ 531 ║ 530 ║
║ merge join ║ 709 ║ 669 ║
║ spool ║ 3202 ║ N/A ║
║ temp insert ║ N/A ║ 422 ║
║ temp scan ║ N/A ║ 187 ║
║ insert ║ 3122 ║ 1545 ║
╚═════════════╩═════════════╩══════════════╝
Kế hoạch truy vấn với bộ đệm háo hức dường như dành nhiều thời gian hơn cho các toán tử chèn và bộ đệm so với kế hoạch sử dụng bảng tạm thời.
Tại sao kế hoạch với bảng tạm thời hiệu quả hơn? Không phải là một spool háo hức chủ yếu chỉ là một bảng tạm thời nội bộ? Tôi tin rằng tôi đang tìm kiếm câu trả lời tập trung vào nội bộ. Tôi có thể thấy các ngăn xếp cuộc gọi khác nhau như thế nào nhưng không thể tìm ra bức tranh lớn.
Tôi đang dùng SQL Server 2017 CU 11 trong trường hợp ai đó muốn biết. Đây là mã để điền vào các bảng được sử dụng trong các truy vấn trên:
DROP TABLE IF EXISTS dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR;
CREATE TABLE dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR (
ID BIGINT NOT NULL,
PRIMARY KEY (ID)
);
INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK)
SELECT TOP (20000000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
CROSS JOIN master..spt_values t3
OPTION (MAXDOP 1);
DROP TABLE IF EXISTS dbo.A_HEAP_OF_MOSTLY_NEW_ROWS;
CREATE TABLE dbo.A_HEAP_OF_MOSTLY_NEW_ROWS (
ID BIGINT NOT NULL
);
INSERT INTO dbo.A_HEAP_OF_MOSTLY_NEW_ROWS WITH (TABLOCK)
SELECT TOP (1900000) 19999999 + ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;