นี่ไม่ใช่คำตอบแบบดั้งเดิม แต่ฉันคิดว่ามันจะมีประโยชน์ในการโพสต์มาตรฐานของเทคนิคบางอย่างที่กล่าวถึง ฉันกำลังทดสอบเซิร์ฟเวอร์หลัก 96 ตัวด้วย SQL Server 2017 CU9
ปัญหาความสามารถในการปรับขนาดได้หลายอย่างเกิดจากเธรดที่เกิดขึ้นพร้อมกันซึ่งมีการแข่งขันกันทั่วโลก ตัวอย่างเช่นพิจารณาข้อขัดแย้งหน้า PFS คลาสสิก สิ่งนี้อาจเกิดขึ้นหากเธรดผู้ปฏิบัติงานจำนวนมากเกินไปจำเป็นต้องแก้ไขหน้าเดียวกันในหน่วยความจำ เมื่อรหัสมีประสิทธิภาพมากขึ้นอาจขอสลักเร็วขึ้น นั่นเป็นการเพิ่มความขัดแย้ง เพื่อให้เข้าใจง่ายโค้ดที่มีประสิทธิภาพมักจะนำไปสู่ปัญหาความสามารถในการปรับขนาดได้เนื่องจากสถานะทั่วโลกถูกโต้แย้งอย่างรุนแรงมากขึ้น รหัสช้ามีแนวโน้มน้อยที่จะทำให้เกิดปัญหาการขยายได้เนื่องจากสถานะสากลไม่ได้เข้าถึงบ่อยครั้ง
HASHBYTES
ความสามารถในการปรับขยายได้บางส่วนขึ้นอยู่กับความยาวของสตริงอินพุต ทฤษฎีของฉันคือสาเหตุที่สิ่งนี้เกิดขึ้นคือการเข้าถึงสถานะโกลบอลบางอย่างจำเป็นเมื่อHASHBYTES
เรียกใช้ฟังก์ชัน สถานะโกลบอลที่ง่ายต่อการสังเกตคือเพจหน่วยความจำที่ต้องจัดสรรต่อการโทรใน SQL Server บางเวอร์ชัน สิ่งที่สังเกตได้ยากกว่าคือมีข้อขัดแย้งของระบบปฏิบัติการบางประเภท ผลHASHBYTES
ก็คือถ้ารหัสถูกเรียกน้อยกว่าการโต้แย้งก็จะลดลง วิธีหนึ่งในการลดอัตราการHASHBYTES
โทรคือการเพิ่มจำนวนของการแฮชที่จำเป็นต่อการโทร งานการแฮชจะขึ้นอยู่กับความยาวของสตริงอินพุตบางส่วน ในการทำซ้ำปัญหาความสามารถในการปรับขนาดที่ฉันเห็นในแอปพลิเคชันฉันจำเป็นต้องเปลี่ยนข้อมูลการสาธิต สถานการณ์กรณีที่เลวร้ายที่สุดที่สมเหตุสมผลคือตารางที่มี 21BIGINT
คอลัมน์ คำจำกัดความของตารางรวมอยู่ในรหัสที่ด้านล่าง เพื่อลด Local Factors ™ฉันใช้การMAXDOP 1
ค้นหาพร้อมกันที่ทำงานบนตารางที่ค่อนข้างเล็ก รหัสมาตรฐานด่วนของฉันอยู่ที่ด้านล่าง
หมายเหตุฟังก์ชั่นคืนค่าแฮชต่างกัน MD5
และSpookyHash
มีทั้งแฮช 128 บิตSHA256
เป็นแฮช 256 บิต
ผลลัพธ์ ( NVARCHAR
เทียบกับVARBINARY
การแปลงและการต่อข้อมูล)
เพื่อที่จะดูว่าการแปลงไปและเชื่อมโยง, VARBINARY
เป็น / performant อย่างแท้จริงที่มีประสิทธิภาพมากขึ้นกว่าที่NVARCHAR
เป็นNVARCHAR
รุ่นของRUN_HASHBYTES_SHA2_256
กระบวนการจัดเก็บที่ถูกสร้างขึ้นจากแม่แบบเดียวกัน (ดู "ขั้นตอนที่ 5" ในเกณฑ์มาตรฐานรหัสด้านล่าง) ข้อแตกต่างคือ:
- ชื่อกระบวนงานที่เก็บไว้จะสิ้นสุดลง
_NVC
BINARY(8)
สำหรับCAST
ฟังก์ชั่นก็เปลี่ยนเป็นNVARCHAR(15)
0x7C
ถูกเปลี่ยนเป็น N'|'
ที่เกิดขึ้นใน:
CAST(FK1 AS NVARCHAR(15)) + N'|' +
แทน:
CAST(FK1 AS BINARY(8)) + 0x7C +
ตารางด้านล่างประกอบด้วยจำนวนของแฮชที่ดำเนินการใน 1 นาที ทำการทดสอบบนเซิร์ฟเวอร์ที่แตกต่างจากที่ใช้สำหรับการทดสอบอื่น ๆ ที่ระบุไว้ด้านล่าง
╔════════════════╦══════════╦══════════════╗
║ Datatype ║ Test # ║ Total Hashes ║
╠════════════════╬══════════╬══════════════╣
║ NVARCHAR ║ 1 ║ 10200000 ║
║ NVARCHAR ║ 2 ║ 10300000 ║
║ NVARCHAR ║ AVERAGE ║ * 10250000 * ║
║ -------------- ║ -------- ║ ------------ ║
║ VARBINARY ║ 1 ║ 12500000 ║
║ VARBINARY ║ 2 ║ 12800000 ║
║ VARBINARY ║ AVERAGE ║ * 12650000 * ║
╚════════════════╩══════════╩══════════════╝
เมื่อดูที่ค่าเฉลี่ยเราสามารถคำนวณข้อดีของการเปลี่ยนเป็นVARBINARY
:
SELECT (12650000 - 10250000) AS [IncreaseAmount],
ROUND(((126500000 - 10250000) / 10250000) * 100.0, 3) AS [IncreasePercentage]
ผลตอบแทนที่ได้:
IncreaseAmount: 2400000.0
IncreasePercentage: 23.415
ผลลัพธ์ (อัลกอริทึมแฮชและการใช้งาน)
ตารางด้านล่างประกอบด้วยจำนวนของแฮชที่ดำเนินการใน 1 นาที ตัวอย่างเช่นการใช้CHECKSUM
84 คิวรีที่เกิดขึ้นพร้อมกันส่งผลให้มีการแฮชมากกว่า 2 พันล้านครั้งก่อนที่เวลาจะหมด
╔════════════════════╦════════════╦════════════╦════════════╗
║ 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 ║
╚════════════════════╩════════════╩════════════╩════════════╝
หากคุณต้องการดูตัวเลขเดียวกันที่วัดได้ในแง่ของการทำงานต่อเธรดที่สอง:
╔════════════════════╦════════════════════════════╦════════════════════════════╦════════════════════════════╗
║ 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 ║
╚════════════════════╩════════════════════════════╩════════════════════════════╩════════════════════════════╝
ความคิดสั้น ๆ เกี่ยวกับวิธีการทั้งหมด:
CHECKSUM
: ความยืดหยุ่นที่ดีมากอย่างที่คาดไว้
HASHBYTES
: ปัญหาเกี่ยวกับความสามารถในการขยายรวมถึงการจัดสรรหน่วยความจำหนึ่งครั้งต่อการโทรหนึ่งครั้งและ CPU จำนวนมากที่ใช้ในระบบปฏิบัติการ
Spooky
: ความยืดหยุ่นที่ดีอย่างน่าประหลาดใจ
Spooky LOB
: spinlock SOS_SELIST_SIZED_SLOCK
หมุนออกจากการควบคุม ฉันสงสัยว่านี่เป็นปัญหาทั่วไปเกี่ยวกับการส่ง LOB ผ่านฟังก์ชั่น CLR แต่ฉันไม่แน่ใจ
Util_HashBinary
: ดูเหมือนว่ามันจะได้รับจาก spinlock เดียวกัน ฉันยังไม่ได้พิจารณาเรื่องนี้มาก่อนเพราะอาจมีอะไรมากมายที่ฉันสามารถทำได้:
Util_HashBinary 8k
: ผลลัพธ์ที่น่าประหลาดใจมากไม่แน่ใจว่าเกิดอะไรขึ้นที่นี่
ผลลัพธ์สุดท้ายทดสอบบนเซิร์ฟเวอร์ที่เล็กกว่า:
╔═════════════════════════╦════════════════════════╦════════════════════════╗
║ 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 ║
╚═════════════════════════╩════════════════════════╩════════════════════════╝
รหัสการสร้างตราสินค้า
การตั้งค่า 1: ตารางและข้อมูล
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
);
การติดตั้ง 2: โปรแกรมประมวลผลหลัก
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
การตั้งค่า 3: Proc การตรวจสอบการชน
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
การตั้งค่า 4: การล้างข้อมูล (DROP All Procs ทดสอบ)
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);
การติดตั้ง 5: สร้างโพรบทดสอบ
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];
การทดสอบ 1: ตรวจสอบการชน
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;
การทดสอบ 2: เรียกใช้การทดสอบประสิทธิภาพ
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;
ปัญหาการตรวจสอบเพื่อแก้ไข
ในขณะที่มุ่งเน้นไปที่การทดสอบประสิทธิภาพของเอกพจน์ SQLCLR UDF, สองประเด็นที่ถูกกล่าวถึงในช่วงต้นไม่ได้ถูกรวมเข้าไปในการทดสอบ แต่ควรที่จะสืบสวนสอบสวนเพื่อตรวจสอบว่าเป็นไปตามวิธีการทั้งหมดของความต้องการ
- ฟังก์ชันจะถูกดำเนินการสองครั้งต่อแต่ละแบบสอบถาม (หนึ่งครั้งสำหรับแถวนำเข้าและอีกครั้งสำหรับแถวปัจจุบัน) การทดสอบจนถึงตอนนี้ได้อ้างอิง UDF เพียงครั้งเดียวในแบบสอบถามการทดสอบ ปัจจัยนี้อาจไม่เปลี่ยนการจัดอันดับของตัวเลือก แต่ไม่ควรเพิกเฉยในกรณีนี้
ในความคิดเห็นที่ถูกลบไปแล้ว Paul White ได้กล่าวถึง:
ข้อเสียเดียวของการแทนที่HASHBYTES
ด้วยฟังก์ชันสเกลาร์ CLR - ปรากฏว่าฟังก์ชั่น CLR ไม่สามารถใช้โหมดแบทช์ในขณะที่HASHBYTES
สามารถ นั่นอาจสำคัญสำหรับประสิทธิภาพ
เพื่อให้เป็นสิ่งที่ต้องพิจารณาและต้องมีการทดสอบอย่างชัดเจน หากตัวเลือก SQLCLR ไม่ได้ให้ประโยชน์ใด ๆ มากกว่าแบบในตัวHASHBYTES
นั่นจะเป็นการเพิ่มน้ำหนักให้กับข้อเสนอแนะของโซโลมอนในการจับแฮชที่มีอยู่ (อย่างน้อยที่สุดก็คือตารางที่ใหญ่ที่สุด) ลงในตารางที่เกี่ยวข้อง
Clear()
วิธีการ แต่ฉันไม่ได้มองไปที่ Spooky