Trong câu hỏi của bạn, bạn nêu chi tiết một số bài kiểm tra mà bạn đã chuẩn bị khi bạn "chứng minh" rằng tùy chọn bổ sung nhanh hơn so với việc so sánh các cột rời rạc. Tôi nghi ngờ phương pháp thử nghiệm của bạn có thể bị thiếu sót theo nhiều cách, vì @gbn và @srutzky đã ám chỉ.
Trước tiên, bạn cần đảm bảo rằng bạn không kiểm tra SQL Server Management Studio (hoặc bất kỳ ứng dụng khách nào bạn đang sử dụng). Chẳng hạn, nếu bạn đang chạy một SELECT *
bảng từ 3 triệu hàng, bạn chủ yếu kiểm tra khả năng của SSMS để kéo các hàng từ SQL Server và hiển thị chúng trên màn hình. Tốt hơn hết là bạn nên sử dụng một cái gì đó như SELECT COUNT(1)
phủ nhận nhu cầu kéo hàng triệu hàng trên mạng và hiển thị chúng trên màn hình.
Thứ hai, bạn cần lưu ý về bộ đệm dữ liệu của SQL Server. Thông thường, chúng tôi kiểm tra tốc độ đọc dữ liệu từ bộ lưu trữ và xử lý dữ liệu đó, từ bộ đệm lạnh (tức là bộ đệm của SQL Server trống). Đôi khi, thật hợp lý khi thực hiện tất cả thử nghiệm của bạn với bộ đệm ấm, nhưng bạn cần tiếp cận thử nghiệm của mình một cách rõ ràng với ý nghĩ đó.
Đối với thử nghiệm bộ đệm lạnh, bạn cần chạy CHECKPOINT
và DBCC DROPCLEANBUFFERS
trước mỗi lần chạy thử.
Đối với bài kiểm tra bạn đã hỏi về câu hỏi của bạn, tôi đã tạo ra bài kiểm tra sau:
IF COALESCE(OBJECT_ID('tempdb..#SomeTest'), 0) <> 0
BEGIN
DROP TABLE #SomeTest;
END
CREATE TABLE #SomeTest
(
TestID INT NOT NULL
PRIMARY KEY
IDENTITY(1,1)
, A INT NOT NULL
, B FLOAT NOT NULL
, C MONEY NOT NULL
, D BIGINT NOT NULL
);
INSERT INTO #SomeTest (A, B, C, D)
SELECT o1.object_id, o2.object_id, o3.object_id, o4.object_id
FROM sys.objects o1
, sys.objects o2
, sys.objects o3
, sys.objects o4;
SELECT COUNT(1)
FROM #SomeTest;
Điều này trả về số lượng 260.144.641 trên máy của tôi.
Để kiểm tra phương pháp "bổ sung", tôi chạy:
CHECKPOINT 5;
DBCC FREEPROCCACHE;
DBCC DROPCLEANBUFFERS;
SET STATISTICS IO, TIME ON;
GO
SELECT COUNT(1)
FROM #SomeTest st
WHERE (st.A + st.B + st.C + st.D) = 0;
GO
SET STATISTICS IO, TIME OFF;
Tab tin nhắn hiển thị:
Bảng '#SomeTest'. Quét số 3, đọc logic 1322661, đọc vật lý 0, đọc trước đọc 1313877, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0.
Thời gian thực thi của máy chủ SQL: Thời gian CPU = 49047 ms, thời gian đã trôi qua = 173451 ms.
Đối với thử nghiệm "cột rời rạc":
CHECKPOINT 5;
DBCC FREEPROCCACHE;
DBCC DROPCLEANBUFFERS;
SET STATISTICS IO, TIME ON;
GO
SELECT COUNT(1)
FROM #SomeTest st
WHERE st.A = 0
AND st.B = 0
AND st.C = 0
AND st.D = 0;
GO
SET STATISTICS IO, TIME OFF;
một lần nữa, từ tab tin nhắn:
Bảng '#SomeTest'. Quét số 3, đọc logic 1322661, đọc vật lý 0, đọc trước đọc 1322661, đọc logic 0, đọc vật lý 0, đọc đọc trước 0, đọc trước 0.
Thời gian thực thi máy chủ SQL: Thời gian CPU = 8938 ms, thời gian trôi qua = 162581 ms.
Từ các số liệu thống kê ở trên, bạn có thể thấy biến thể thứ hai, với các cột rời rạc so với 0, thời gian trôi qua ngắn hơn khoảng 10 giây và thời gian CPU ít hơn khoảng 6 lần. Thời lượng dài trong các thử nghiệm của tôi ở trên chủ yếu là kết quả của việc đọc rất nhiều hàng từ đĩa. Nếu bạn giảm số lượng hàng xuống còn 3 triệu, bạn sẽ thấy các tỷ lệ vẫn giữ nguyên nhưng thời gian trôi qua giảm đáng kể, vì I / O của đĩa có ít tác dụng hơn.
Với phương pháp "Bổ sung":
Bảng '#SomeTest'. Quét số 3, đọc logic 15255, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.
Thời gian thực thi máy chủ SQL: Thời gian CPU = 499 ms, thời gian trôi qua = 256 ms.
Với phương pháp "cột rời rạc":
Bảng '#SomeTest'. Quét số 3, đọc logic 15255, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.
Thời gian thực thi máy chủ SQL: Thời gian CPU = 94 ms, thời gian trôi qua = 53 ms.
Điều gì sẽ tạo ra một sự khác biệt thực sự lớn cho bài kiểm tra này? Một chỉ số thích hợp, chẳng hạn như:
CREATE INDEX IX_SomeTest ON #SomeTest(A, B, C, D);
Phương pháp "bổ sung":
Bảng '#SomeTest'. Quét số 3, đọc logic 14235, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.
Thời gian thực thi máy chủ SQL: Thời gian CPU = 546 ms, thời gian trôi qua = 314 ms.
Phương pháp "cột rời rạc":
Bảng '#SomeTest'. Quét số 1, đọc logic 3, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.
Thời gian thực thi máy chủ SQL: Thời gian CPU = 0 ms, thời gian trôi qua = 0 ms.
Kế hoạch thực hiện cho từng truy vấn (với chỉ mục ở trên tại chỗ) là khá rõ ràng.
Phương thức "bổ sung", phải thực hiện quét toàn bộ chỉ mục:
và phương thức "các cột rời rạc", có thể tìm đến hàng đầu tiên của chỉ mục trong đó cột chỉ mục hàng đầu A
, bằng không: