Một phần khối lượng công việc của tôi sử dụng hàm CLR thực hiện thuật toán băm ma quái để so sánh các hàng để xem có giá trị cột nào thay đổi không. Hàm CLR lấy một chuỗi nhị phân làm đầu vào, vì vậy tôi cần một cách nhanh chóng để chuyển đổi các hàng thành chuỗi nhị phân. Tôi hy vọng sẽ băm khoảng 10 tỷ hàng trong toàn bộ khối lượng công việc vì vậy tôi muốn mã này nhanh nhất có thể.
Tôi có khoảng 300 bảng với các lược đồ khác nhau. Đối với mục đích của câu hỏi này, vui lòng giả sử cấu trúc bảng đơn giản gồm 32 INT
cột không thể. Tôi đã cung cấp dữ liệu mẫu cũng như một cách để kết quả điểm chuẩn ở cuối câu hỏi này.
Các hàng phải được chuyển đổi thành cùng một chuỗi nhị phân nếu tất cả các giá trị cột giống nhau. Các hàng phải được chuyển đổi thành các chuỗi nhị phân khác nhau nếu bất kỳ giá trị cột nào khác nhau. Ví dụ, mã đơn giản như sau sẽ không hoạt động:
CAST(COL1 AS BINARY(4)) + CAST(COL2 AS BINARY(4)) + ..
Nó không xử lý NULL chính xác. Nếu COL1
là NULL cho hàng 1 và COL2
là NULL cho hàng 2 thì cả hai hàng sẽ được chuyển đổi thành chuỗi NULL. Tôi tin rằng việc xử lý chính xác các NULL là phần khó nhất để chuyển đổi toàn bộ hàng một cách chính xác. Tất cả các giá trị được phép cho các cột INT là có thể.
Để tránh một số câu hỏi:
- Nếu có vấn đề, phần lớn thời gian (90% +) các cột sẽ không phải là NULL.
- Tôi phải sử dụng CLR.
- Tôi phải băm nhiều hàng này. Tôi không thể kiên trì băm.
- Tôi tin rằng tôi không thể sử dụng chế độ hàng loạt cho chuyển đổi do sự hiện diện của chức năng CLR.
Cách nhanh nhất để chuyển đổi 32 INT
cột nullable thành một chuỗi BINARY(X)
hoặc là VARBINARY(X)
gì?
Dữ liệu mẫu và mã như đã hứa:
-- create sample data
DROP TABLE IF EXISTS dbo.TABLE_OF_32_INTS;
CREATE TABLE dbo.TABLE_OF_32_INTS (
COL1 INT NULL,
COL2 INT NULL,
COL3 INT NULL,
COL4 INT NULL,
COL5 INT NULL,
COL6 INT NULL,
COL7 INT NULL,
COL8 INT NULL,
COL9 INT NULL,
COL10 INT NULL,
COL11 INT NULL,
COL12 INT NULL,
COL13 INT NULL,
COL14 INT NULL,
COL15 INT NULL,
COL16 INT NULL,
COL17 INT NULL,
COL18 INT NULL,
COL19 INT NULL,
COL20 INT NULL,
COL21 INT NULL,
COL22 INT NULL,
COL23 INT NULL,
COL24 INT NULL,
COL25 INT NULL,
COL26 INT NULL,
COL27 INT NULL,
COL28 INT NULL,
COL29 INT NULL,
COL30 INT NULL,
COL31 INT NULL,
COL32 INT NULL
);
INSERT INTO dbo.TABLE_OF_32_INTS WITH (TABLOCK)
SELECT 0, 123, 12345, 1234567, 123456789
, 0, 123, 12345, 1234567, 123456789
, 0, 123, 12345, 1234567, 123456789
, 0, 123, 12345, 1234567, 123456789
, 0, 123, 12345, 1234567, 123456789
, 0, 123, 12345, 1234567, 123456789
, NULL, -876545321
FROM
(
SELECT TOP (1000000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
) q
OPTION (MAXDOP 1);
GO
-- procedure to test performance
CREATE OR ALTER PROCEDURE #p AS
BEGIN
SET NOCOUNT ON;
DECLARE
@counter INT = 0,
@dummy VARBINARY(8000);
WHILE @counter < 10
BEGIN
SELECT @dummy = -- this code is clearly incomplete as it does not handle NULLs
CAST(COL1 AS BINARY(4)) +
CAST(COL2 AS BINARY(4)) +
CAST(COL3 AS BINARY(4)) +
CAST(COL4 AS BINARY(4)) +
CAST(COL5 AS BINARY(4)) +
CAST(COL6 AS BINARY(4)) +
CAST(COL7 AS BINARY(4)) +
CAST(COL8 AS BINARY(4)) +
CAST(COL9 AS BINARY(4)) +
CAST(COL10 AS BINARY(4)) +
CAST(COL11 AS BINARY(4)) +
CAST(COL12 AS BINARY(4)) +
CAST(COL13 AS BINARY(4)) +
CAST(COL14 AS BINARY(4)) +
CAST(COL15 AS BINARY(4)) +
CAST(COL16 AS BINARY(4)) +
CAST(COL17 AS BINARY(4)) +
CAST(COL18 AS BINARY(4)) +
CAST(COL19 AS BINARY(4)) +
CAST(COL20 AS BINARY(4)) +
CAST(COL21 AS BINARY(4)) +
CAST(COL22 AS BINARY(4)) +
CAST(COL23 AS BINARY(4)) +
CAST(COL24 AS BINARY(4)) +
CAST(COL25 AS BINARY(4)) +
CAST(COL26 AS BINARY(4)) +
CAST(COL27 AS BINARY(4)) +
CAST(COL28 AS BINARY(4)) +
CAST(COL29 AS BINARY(4)) +
CAST(COL30 AS BINARY(4)) +
CAST(COL31 AS BINARY(4)) +
CAST(COL32 AS BINARY(4))
FROM dbo.TABLE_OF_32_INTS
OPTION (MAXDOP 1);
SET @counter = @counter + 1;
END;
SELECT cpu_time
FROM sys.dm_exec_requests
WHERE session_id = @@SPID;
END;
GO
-- run procedure
EXEC #p;
(Tôi vẫn sẽ sử dụng hàm băm ma quái trên kết quả nhị phân này. Khối lượng công việc sử dụng phép nối băm và giá trị băm được sử dụng cho một trong các bản dựng băm. Tôi không muốn giá trị nhị phân dài trong bản dựng băm vì nó đòi hỏi quá nhiều ký ức.)