Ini bukan jawaban tradisional, tapi saya pikir akan sangat membantu untuk mengirim tolok ukur dari beberapa teknik yang disebutkan sejauh ini. Saya menguji pada server inti 96 dengan SQL Server 2017 CU9.
Banyak masalah skalabilitas disebabkan oleh utas bersamaan yang bersaing atas beberapa negara global. Sebagai contoh, pertimbangkan pertengkaran halaman PFS klasik. Ini bisa terjadi jika terlalu banyak utas pekerja perlu memodifikasi halaman yang sama dalam memori. Karena kode menjadi lebih efisien, ia dapat meminta kait lebih cepat. Itu meningkatkan pertikaian. Sederhananya, kode efisien lebih cenderung menyebabkan masalah skalabilitas karena negara global diperebutkan lebih parah. Kode lambat cenderung menyebabkan masalah skalabilitas karena negara global tidak sering diakses.
HASHBYTES
skalabilitas sebagian didasarkan pada panjang string input. Teori saya adalah mengapa ini terjadi adalah bahwa akses ke beberapa negara global diperlukan ketika HASHBYTES
fungsi dipanggil. Status global yang mudah diamati adalah halaman memori perlu dialokasikan per panggilan pada beberapa versi SQL Server. Yang lebih sulit untuk diamati adalah bahwa ada semacam pertikaian OS. Akibatnya, jika HASHBYTES
dipanggil dengan kode lebih jarang maka pertikaian turun. Salah satu cara untuk mengurangi laju kolom. Definisi tabel termasuk dalam kode di bagian bawah. Untuk mengurangi Local Factors ™, saya menggunakan kueri bersamaan yang beroperasi pada tabel yang relatif kecil. Kode tolok ukur cepat saya ada di bagian bawah.HASHBYTES
panggilan adalah dengan meningkatkan jumlah pekerjaan hashing yang dibutuhkan per panggilan. Pekerjaan hashing sebagian didasarkan pada panjang string input. Untuk mereproduksi masalah skalabilitas yang saya lihat di aplikasi saya perlu mengubah data demo. Skenario terburuk yang masuk akal adalah tabel dengan 21BIGINT
MAXDOP 1
Perhatikan fungsi mengembalikan panjang hash yang berbeda. MD5
dan SpookyHash
keduanya hash 128 bit, SHA256
adalah hash 256 bit.
HASIL ( NVARCHAR
vs VARBINARY
konversi dan gabungan)
Untuk mengetahui apakah mengonversikan ke, dan menggabungkan, VARBINARY
benar-benar lebih efisien / berkinerja daripada NVARCHAR
, NVARCHAR
versi RUN_HASHBYTES_SHA2_256
prosedur yang tersimpan dibuat dari templat yang sama (lihat "Langkah 5" di bagian KODE BENCHMARKING CODE di bawah). Satu-satunya perbedaan adalah:
- Nama Prosedur yang Disimpan berakhir dengan
_NVC
BINARY(8)
untuk CAST
fungsi diubah menjadiNVARCHAR(15)
0x7C
diubah menjadi N'|'
Yang menghasilkan:
CAST(FK1 AS NVARCHAR(15)) + N'|' +
dari pada:
CAST(FK1 AS BINARY(8)) + 0x7C +
Tabel di bawah ini berisi jumlah hash yang dilakukan dalam 1 menit. Tes dilakukan pada server yang berbeda dari yang digunakan untuk tes lain yang disebutkan di bawah ini.
╔════════════════╦══════════╦══════════════╗
║ Datatype ║ Test # ║ Total Hashes ║
╠════════════════╬══════════╬══════════════╣
║ NVARCHAR ║ 1 ║ 10200000 ║
║ NVARCHAR ║ 2 ║ 10300000 ║
║ NVARCHAR ║ AVERAGE ║ * 10250000 * ║
║ -------------- ║ -------- ║ ------------ ║
║ VARBINARY ║ 1 ║ 12500000 ║
║ VARBINARY ║ 2 ║ 12800000 ║
║ VARBINARY ║ AVERAGE ║ * 12650000 * ║
╚════════════════╩══════════╩══════════════╝
Melihat rata-rata saja, kita dapat menghitung manfaat beralih ke VARBINARY
:
SELECT (12650000 - 10250000) AS [IncreaseAmount],
ROUND(((126500000 - 10250000) / 10250000) * 100.0, 3) AS [IncreasePercentage]
Itu kembali:
IncreaseAmount: 2400000.0
IncreasePercentage: 23.415
HASIL (algoritme dan implementasi hash)
Tabel di bawah ini berisi jumlah hash yang dilakukan dalam 1 menit. Misalnya, menggunakan CHECKSUM
dengan 84 kueri bersamaan menghasilkan lebih dari 2 miliar hash dilakukan sebelum waktu habis.
╔════════════════════╦════════════╦════════════╦════════════╗
║ Function ║ 12 threads ║ 48 threads ║ 84 threads ║
╠════════════════════╬════════════╬════════════╬════════════╣
║ CHECKSUM ║ 281250000 ║ 1122440000 ║ 2040100000 ║
║ HASHBYTES MD5 ║ 75940000 ║ 106190000 ║ 112750000 ║
║ HASHBYTES SHA2_256 ║ 80210000 ║ 117080000 ║ 124790000 ║
║ CLR Spooky ║ 131250000 ║ 505700000 ║ 786150000 ║
║ CLR SpookyLOB ║ 17420000 ║ 27160000 ║ 31380000 ║
║ SQL# MD5 ║ 17080000 ║ 26450000 ║ 29080000 ║
║ SQL# SHA2_256 ║ 18370000 ║ 28860000 ║ 32590000 ║
║ SQL# MD5 8k ║ 24440000 ║ 30560000 ║ 32550000 ║
║ SQL# SHA2_256 8k ║ 87240000 ║ 159310000 ║ 155760000 ║
╚════════════════════╩════════════╩════════════╩════════════╝
Jika Anda lebih suka melihat angka yang sama diukur dalam hal kerja per utas-detik:
╔════════════════════╦════════════════════════════╦════════════════════════════╦════════════════════════════╗
║ Function ║ 12 threads per core-second ║ 48 threads per core-second ║ 84 threads per core-second ║
╠════════════════════╬════════════════════════════╬════════════════════════════╬════════════════════════════╣
║ CHECKSUM ║ 390625 ║ 389736 ║ 404782 ║
║ HASHBYTES MD5 ║ 105472 ║ 36872 ║ 22371 ║
║ HASHBYTES SHA2_256 ║ 111403 ║ 40653 ║ 24760 ║
║ CLR Spooky ║ 182292 ║ 175590 ║ 155982 ║
║ CLR SpookyLOB ║ 24194 ║ 9431 ║ 6226 ║
║ SQL# MD5 ║ 23722 ║ 9184 ║ 5770 ║
║ SQL# SHA2_256 ║ 25514 ║ 10021 ║ 6466 ║
║ SQL# MD5 8k ║ 33944 ║ 10611 ║ 6458 ║
║ SQL# SHA2_256 8k ║ 121167 ║ 55316 ║ 30905 ║
╚════════════════════╩════════════════════════════╩════════════════════════════╩════════════════════════════╝
Beberapa pemikiran cepat tentang semua metode:
CHECKSUM
: skalabilitas yang sangat baik seperti yang diharapkan
HASHBYTES
: masalah skalabilitas mencakup satu alokasi memori per panggilan dan sejumlah besar CPU yang dihabiskan di OS
Spooky
: skalabilitas yang sangat baik
Spooky LOB
: spinlock SOS_SELIST_SIZED_SLOCK
berputar di luar kendali. Saya menduga ini adalah masalah umum dengan melewatkan LOB melalui fungsi CLR, tapi saya tidak yakin
Util_HashBinary
: sepertinya akan terkena spinlock yang sama. Saya belum melihat sejauh ini karena mungkin tidak banyak yang bisa saya lakukan tentang hal ini:
Util_HashBinary 8k
: hasil yang sangat mengejutkan, tidak yakin apa yang terjadi di sini
Hasil akhir diuji pada server yang lebih kecil:
╔═════════════════════════╦════════════════════════╦════════════════════════╗
║ Hash Algorithm ║ Hashes over 11 threads ║ Hashes over 44 threads ║
╠═════════════════════════╬════════════════════════╬════════════════════════╣
║ HASHBYTES SHA2_256 ║ 85220000 ║ 167050000 ║
║ SpookyHash ║ 101200000 ║ 239530000 ║
║ Util_HashSHA256Binary8k ║ 90590000 ║ 217170000 ║
║ SpookyHashLOB ║ 23490000 ║ 38370000 ║
║ Util_HashSHA256Binary ║ 23430000 ║ 36590000 ║
╚═════════════════════════╩════════════════════════╩════════════════════════╝
KODE BENCHMARKING
SETUP 1: Tabel dan Data
DROP TABLE IF EXISTS dbo.HASH_SMALL;
CREATE TABLE dbo.HASH_SMALL (
ID BIGINT NOT NULL,
FK1 BIGINT NOT NULL,
FK2 BIGINT NOT NULL,
FK3 BIGINT NOT NULL,
FK4 BIGINT NOT NULL,
FK5 BIGINT NOT NULL,
FK6 BIGINT NOT NULL,
FK7 BIGINT NOT NULL,
FK8 BIGINT NOT NULL,
FK9 BIGINT NOT NULL,
FK10 BIGINT NOT NULL,
FK11 BIGINT NOT NULL,
FK12 BIGINT NOT NULL,
FK13 BIGINT NOT NULL,
FK14 BIGINT NOT NULL,
FK15 BIGINT NOT NULL,
FK16 BIGINT NOT NULL,
FK17 BIGINT NOT NULL,
FK18 BIGINT NOT NULL,
FK19 BIGINT NOT NULL,
FK20 BIGINT NOT NULL
);
INSERT INTO dbo.HASH_SMALL WITH (TABLOCK)
SELECT RN,
4000000 - RN, 4000000 - RN
,200000000 - RN, 200000000 - RN
, RN % 500000 , RN % 500000 , RN % 500000
, RN % 500000 , RN % 500000 , RN % 500000
, 100000 - RN % 100000, RN % 100000
, 100000 - RN % 100000, RN % 100000
, 100000 - RN % 100000, RN % 100000
, 100000 - RN % 100000, RN % 100000
, 100000 - RN % 100000, RN % 100000
FROM (
SELECT TOP (10000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
) q
OPTION (MAXDOP 1);
DROP TABLE IF EXISTS dbo.LOG_HASHES;
CREATE TABLE dbo.LOG_HASHES (
LOG_TIME DATETIME,
HASH_ALGORITHM INT,
SESSION_ID INT,
NUM_HASHES BIGINT
);
SETUP 2: Proc Master Eksekusi
GO
CREATE OR ALTER PROCEDURE dbo.RUN_HASHES_FOR_ONE_MINUTE (@HashAlgorithm INT)
AS
BEGIN
DECLARE @target_end_time DATETIME = DATEADD(MINUTE, 1, GETDATE()),
@query_execution_count INT = 0;
SET NOCOUNT ON;
DECLARE @ProcName NVARCHAR(261); -- schema_name + proc_name + '[].[]'
DECLARE @RowCount INT;
SELECT @RowCount = SUM(prtn.[row_count])
FROM sys.dm_db_partition_stats prtn
WHERE prtn.[object_id] = OBJECT_ID(N'dbo.HASH_SMALL')
AND prtn.[index_id] < 2;
-- Load assembly if not loaded to prevent load time from skewing results
DECLARE @OptionalInitSQL NVARCHAR(MAX);
SET @OptionalInitSQL = CASE @HashAlgorithm
WHEN 1 THEN N'SELECT @Dummy = dbo.SpookyHash(0x1234);'
WHEN 2 THEN N'' -- HASHBYTES
WHEN 3 THEN N'' -- HASHBYTES
WHEN 4 THEN N'' -- CHECKSUM
WHEN 5 THEN N'SELECT @Dummy = dbo.SpookyHashLOB(0x1234);'
WHEN 6 THEN N'SELECT @Dummy = SQL#.Util_HashBinary(N''MD5'', 0x1234);'
WHEN 7 THEN N'SELECT @Dummy = SQL#.Util_HashBinary(N''SHA256'', 0x1234);'
WHEN 8 THEN N'SELECT @Dummy = SQL#.Util_HashBinary8k(N''MD5'', 0x1234);'
WHEN 9 THEN N'SELECT @Dummy = SQL#.Util_HashBinary8k(N''SHA256'', 0x1234);'
/* -- BETA / non-public code
WHEN 10 THEN N'SELECT @Dummy = SQL#.Util_HashSHA256Binary8k(0x1234);'
WHEN 11 THEN N'SELECT @Dummy = SQL#.Util_HashSHA256Binary(0x1234);'
*/
END;
IF (RTRIM(@OptionalInitSQL) <> N'')
BEGIN
SET @OptionalInitSQL = N'
SET NOCOUNT ON;
DECLARE @Dummy VARBINARY(100);
' + @OptionalInitSQL;
RAISERROR(N'** Executing optional initialization code:', 10, 1) WITH NOWAIT;
RAISERROR(@OptionalInitSQL, 10, 1) WITH NOWAIT;
EXEC (@OptionalInitSQL);
RAISERROR(N'-------------------------------------------', 10, 1) WITH NOWAIT;
END;
SET @ProcName = CASE @HashAlgorithm
WHEN 1 THEN N'dbo.RUN_SpookyHash'
WHEN 2 THEN N'dbo.RUN_HASHBYTES_MD5'
WHEN 3 THEN N'dbo.RUN_HASHBYTES_SHA2_256'
WHEN 4 THEN N'dbo.RUN_CHECKSUM'
WHEN 5 THEN N'dbo.RUN_SpookyHashLOB'
WHEN 6 THEN N'dbo.RUN_SR_MD5'
WHEN 7 THEN N'dbo.RUN_SR_SHA256'
WHEN 8 THEN N'dbo.RUN_SR_MD5_8k'
WHEN 9 THEN N'dbo.RUN_SR_SHA256_8k'
/* -- BETA / non-public code
WHEN 10 THEN N'dbo.RUN_SR_SHA256_new'
WHEN 11 THEN N'dbo.RUN_SR_SHA256LOB_new'
*/
WHEN 13 THEN N'dbo.RUN_HASHBYTES_SHA2_256_NVC'
END;
RAISERROR(N'** Executing proc: %s', 10, 1, @ProcName) WITH NOWAIT;
WHILE GETDATE() < @target_end_time
BEGIN
EXEC @ProcName;
SET @query_execution_count = @query_execution_count + 1;
END;
INSERT INTO dbo.LOG_HASHES
VALUES (GETDATE(), @HashAlgorithm, @@SPID, @RowCount * @query_execution_count);
END;
GO
SETUP 3: Proc Detection Collision
GO
CREATE OR ALTER PROCEDURE dbo.VERIFY_NO_COLLISIONS (@HashAlgorithm INT)
AS
SET NOCOUNT ON;
DECLARE @RowCount INT;
SELECT @RowCount = SUM(prtn.[row_count])
FROM sys.dm_db_partition_stats prtn
WHERE prtn.[object_id] = OBJECT_ID(N'dbo.HASH_SMALL')
AND prtn.[index_id] < 2;
DECLARE @CollisionTestRows INT;
DECLARE @CollisionTestSQL NVARCHAR(MAX);
SET @CollisionTestSQL = N'
SELECT @RowsOut = COUNT(DISTINCT '
+ CASE @HashAlgorithm
WHEN 1 THEN N'dbo.SpookyHash('
WHEN 2 THEN N'HASHBYTES(''MD5'','
WHEN 3 THEN N'HASHBYTES(''SHA2_256'','
WHEN 4 THEN N'CHECKSUM('
WHEN 5 THEN N'dbo.SpookyHashLOB('
WHEN 6 THEN N'SQL#.Util_HashBinary(N''MD5'','
WHEN 7 THEN N'SQL#.Util_HashBinary(N''SHA256'','
WHEN 8 THEN N'SQL#.[Util_HashBinary8k](N''MD5'','
WHEN 9 THEN N'SQL#.[Util_HashBinary8k](N''SHA256'','
--/* -- BETA / non-public code
WHEN 10 THEN N'SQL#.[Util_HashSHA256Binary8k]('
WHEN 11 THEN N'SQL#.[Util_HashSHA256Binary]('
--*/
END
+ N'
CAST(FK1 AS BINARY(8)) + 0x7C +
CAST(FK2 AS BINARY(8)) + 0x7C +
CAST(FK3 AS BINARY(8)) + 0x7C +
CAST(FK4 AS BINARY(8)) + 0x7C +
CAST(FK5 AS BINARY(8)) + 0x7C +
CAST(FK6 AS BINARY(8)) + 0x7C +
CAST(FK7 AS BINARY(8)) + 0x7C +
CAST(FK8 AS BINARY(8)) + 0x7C +
CAST(FK9 AS BINARY(8)) + 0x7C +
CAST(FK10 AS BINARY(8)) + 0x7C +
CAST(FK11 AS BINARY(8)) + 0x7C +
CAST(FK12 AS BINARY(8)) + 0x7C +
CAST(FK13 AS BINARY(8)) + 0x7C +
CAST(FK14 AS BINARY(8)) + 0x7C +
CAST(FK15 AS BINARY(8)) + 0x7C +
CAST(FK16 AS BINARY(8)) + 0x7C +
CAST(FK17 AS BINARY(8)) + 0x7C +
CAST(FK18 AS BINARY(8)) + 0x7C +
CAST(FK19 AS BINARY(8)) + 0x7C +
CAST(FK20 AS BINARY(8)) ))
FROM dbo.HASH_SMALL;';
PRINT @CollisionTestSQL;
EXEC sp_executesql
@CollisionTestSQL,
N'@RowsOut INT OUTPUT',
@RowsOut = @CollisionTestRows OUTPUT;
IF (@CollisionTestRows <> @RowCount)
BEGIN
RAISERROR('Collisions for algorithm: %d!!! %d unique rows out of %d.',
16, 1, @HashAlgorithm, @CollisionTestRows, @RowCount);
END;
GO
SETUP 4: Pembersihan (DROP Semua Procs Tes)
DECLARE @SQL NVARCHAR(MAX) = N'';
SELECT @SQL += N'DROP PROCEDURE [dbo].' + QUOTENAME(sp.[name])
+ N';' + NCHAR(13) + NCHAR(10)
FROM sys.objects sp
WHERE sp.[name] LIKE N'RUN[_]%'
AND sp.[type_desc] = N'SQL_STORED_PROCEDURE'
AND sp.[name] <> N'RUN_HASHES_FOR_ONE_MINUTE'
PRINT @SQL;
EXEC (@SQL);
SETUP 5: Hasilkan Procs Tes
SET NOCOUNT ON;
DECLARE @TestProcsToCreate TABLE
(
ProcName sysname NOT NULL,
CodeToExec NVARCHAR(261) NOT NULL
);
DECLARE @ProcName sysname,
@CodeToExec NVARCHAR(261);
INSERT INTO @TestProcsToCreate VALUES
(N'SpookyHash', N'dbo.SpookyHash('),
(N'HASHBYTES_MD5', N'HASHBYTES(''MD5'','),
(N'HASHBYTES_SHA2_256', N'HASHBYTES(''SHA2_256'','),
(N'CHECKSUM', N'CHECKSUM('),
(N'SpookyHashLOB', N'dbo.SpookyHashLOB('),
(N'SR_MD5', N'SQL#.Util_HashBinary(N''MD5'','),
(N'SR_SHA256', N'SQL#.Util_HashBinary(N''SHA256'','),
(N'SR_MD5_8k', N'SQL#.[Util_HashBinary8k](N''MD5'','),
(N'SR_SHA256_8k', N'SQL#.[Util_HashBinary8k](N''SHA256'',')
--/* -- BETA / non-public code
, (N'SR_SHA256_new', N'SQL#.[Util_HashSHA256Binary8k]('),
(N'SR_SHA256LOB_new', N'SQL#.[Util_HashSHA256Binary](');
--*/
DECLARE @ProcTemplate NVARCHAR(MAX),
@ProcToCreate NVARCHAR(MAX);
SET @ProcTemplate = N'
CREATE OR ALTER PROCEDURE dbo.RUN_{{ProcName}}
AS
BEGIN
DECLARE @dummy INT;
SET NOCOUNT ON;
SELECT @dummy = COUNT({{CodeToExec}}
CAST(FK1 AS BINARY(8)) + 0x7C +
CAST(FK2 AS BINARY(8)) + 0x7C +
CAST(FK3 AS BINARY(8)) + 0x7C +
CAST(FK4 AS BINARY(8)) + 0x7C +
CAST(FK5 AS BINARY(8)) + 0x7C +
CAST(FK6 AS BINARY(8)) + 0x7C +
CAST(FK7 AS BINARY(8)) + 0x7C +
CAST(FK8 AS BINARY(8)) + 0x7C +
CAST(FK9 AS BINARY(8)) + 0x7C +
CAST(FK10 AS BINARY(8)) + 0x7C +
CAST(FK11 AS BINARY(8)) + 0x7C +
CAST(FK12 AS BINARY(8)) + 0x7C +
CAST(FK13 AS BINARY(8)) + 0x7C +
CAST(FK14 AS BINARY(8)) + 0x7C +
CAST(FK15 AS BINARY(8)) + 0x7C +
CAST(FK16 AS BINARY(8)) + 0x7C +
CAST(FK17 AS BINARY(8)) + 0x7C +
CAST(FK18 AS BINARY(8)) + 0x7C +
CAST(FK19 AS BINARY(8)) + 0x7C +
CAST(FK20 AS BINARY(8))
)
)
FROM dbo.HASH_SMALL
OPTION (MAXDOP 1);
END;
';
DECLARE CreateProcsCurs CURSOR READ_ONLY FORWARD_ONLY LOCAL FAST_FORWARD
FOR SELECT [ProcName], [CodeToExec]
FROM @TestProcsToCreate;
OPEN [CreateProcsCurs];
FETCH NEXT
FROM [CreateProcsCurs]
INTO @ProcName, @CodeToExec;
WHILE (@@FETCH_STATUS = 0)
BEGIN
-- First: create VARBINARY version
SET @ProcToCreate = REPLACE(REPLACE(@ProcTemplate,
N'{{ProcName}}',
@ProcName),
N'{{CodeToExec}}',
@CodeToExec);
EXEC (@ProcToCreate);
-- Second: create NVARCHAR version (optional: built-ins only)
IF (CHARINDEX(N'.', @CodeToExec) = 0)
BEGIN
SET @ProcToCreate = REPLACE(REPLACE(REPLACE(@ProcToCreate,
N'dbo.RUN_' + @ProcName,
N'dbo.RUN_' + @ProcName + N'_NVC'),
N'BINARY(8)',
N'NVARCHAR(15)'),
N'0x7C',
N'N''|''');
EXEC (@ProcToCreate);
END;
FETCH NEXT
FROM [CreateProcsCurs]
INTO @ProcName, @CodeToExec;
END;
CLOSE [CreateProcsCurs];
DEALLOCATE [CreateProcsCurs];
UJI 1: Periksa Tabrakan
EXEC dbo.VERIFY_NO_COLLISIONS 1;
EXEC dbo.VERIFY_NO_COLLISIONS 2;
EXEC dbo.VERIFY_NO_COLLISIONS 3;
EXEC dbo.VERIFY_NO_COLLISIONS 4;
EXEC dbo.VERIFY_NO_COLLISIONS 5;
EXEC dbo.VERIFY_NO_COLLISIONS 6;
EXEC dbo.VERIFY_NO_COLLISIONS 7;
EXEC dbo.VERIFY_NO_COLLISIONS 8;
EXEC dbo.VERIFY_NO_COLLISIONS 9;
EXEC dbo.VERIFY_NO_COLLISIONS 10;
EXEC dbo.VERIFY_NO_COLLISIONS 11;
TEST 2: Jalankan Tes Kinerja
EXEC dbo.RUN_HASHES_FOR_ONE_MINUTE 1;
EXEC dbo.RUN_HASHES_FOR_ONE_MINUTE 2;
EXEC dbo.RUN_HASHES_FOR_ONE_MINUTE 3; -- HASHBYTES('SHA2_256'
EXEC dbo.RUN_HASHES_FOR_ONE_MINUTE 4;
EXEC dbo.RUN_HASHES_FOR_ONE_MINUTE 5;
EXEC dbo.RUN_HASHES_FOR_ONE_MINUTE 6;
EXEC dbo.RUN_HASHES_FOR_ONE_MINUTE 7;
EXEC dbo.RUN_HASHES_FOR_ONE_MINUTE 8;
EXEC dbo.RUN_HASHES_FOR_ONE_MINUTE 9;
EXEC dbo.RUN_HASHES_FOR_ONE_MINUTE 10;
EXEC dbo.RUN_HASHES_FOR_ONE_MINUTE 11;
EXEC dbo.RUN_HASHES_FOR_ONE_MINUTE 13; -- NVC version of #3
SELECT *
FROM dbo.LOG_HASHES
ORDER BY [LOG_TIME] DESC;
MASALAH VALIDASI UNTUK MENYELESAIKAN
Sementara berfokus pada pengujian kinerja SQLCLR UDF tunggal, dua masalah yang dibahas sejak awal tidak dimasukkan ke dalam tes, tetapi idealnya harus diselidiki untuk menentukan pendekatan mana yang memenuhi semua persyaratan.
- Fungsi ini akan dieksekusi dua kali per setiap kueri (satu kali untuk baris impor, dan satu kali untuk baris saat ini). Tes sejauh ini hanya merujuk UDF satu kali dalam pertanyaan tes. Faktor ini mungkin tidak mengubah peringkat opsi, tetapi tidak boleh diabaikan, untuk berjaga-jaga.
Dalam komentar yang telah dihapus, Paul White menyebutkan:
Satu kelemahan dari penggantian HASHBYTES
dengan fungsi skalar CLR - tampaknya fungsi CLR tidak dapat menggunakan mode batch sedangkan HASHBYTES
bisa. Itu mungkin penting, kinerja-bijaksana.
Jadi itu adalah sesuatu yang perlu dipertimbangkan, dan jelas membutuhkan pengujian. Jika opsi SQLCLR tidak memberikan manfaat apa pun atas built-in HASHBYTES
, maka itu menambah bobot saran Solomon untuk menangkap hash yang ada (untuk setidaknya tabel terbesar) ke dalam tabel terkait.
Clear()
metode tetapi saya belum melihat sejauh itu ke Spooky.SHA256Managed
danSpookyHashV2
, tetapi saya mencoba ini dan tidak melihat banyak, jika ada, peningkatan kinerja. Saya juga memperhatikan bahwaManagedThreadId
nilainya sama untuk semua referensi SQLCLR dalam permintaan tertentu. Saya menguji beberapa referensi ke fungsi yang sama, serta referensi ke fungsi yang berbeda, ketiganya diberi nilai input yang berbeda, dan mengembalikan nilai pengembalian yang berbeda (tetapi diharapkan). Bukankah ini meningkatkan peluang kondisi balapan? Agar adil, dalam pengujian saya, saya tidak melihat apa pun.