几年来,我们一直在某些 SQL Server 2012 实例上使用对称 key 进行加密/解密。我们最近安装了一些新的 SQL Server 2014 实例,并在解密 SQL Server 2014 安装上的数据时遇到了一些性能问题。
考虑一个如下所示的表格:
CREATE TABLE [dbo].[tblCertTest](
[article_id_enc] [varbinary](100) NOT NULL,
[article_id] [int] NULL
) ON [PRIMARY]
key 和证书创建如下:
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Passwrrrrd12'
CREATE CERTIFICATE MyCertificateName
WITH SUBJECT = 'A label for this certificate'
CREATE SYMMETRIC KEY MySymmetricKeyName WITH
IDENTITY_VALUE = 'a fairly secure name',
ALGORITHM = AES_256,
KEY_SOURCE = 'a very secure strong password or phrase'
ENCRYPTION BY CERTIFICATE MyCertificateName;
我们的数据集大约有 90000 行,article_id 是一个 5 位数字。稍微简化一下,article_id_enc 使用以下命令进行加密:
update tblCertTest set article_id_enc = ENCRYPTBYKEY(KEY_GUID('MySymmetricKeyName'),convert(varbinary(100), article_id))
我们已经应用了所有可用的修补程序,我们尝试了 SQL Server 2012 和 SQL Server 2014 的不同实例以及不同的设置,例如 SSD 磁盘、RAM 磁盘等。
我们已经在 SQL Server 上本地和远程尝试了查询。
所有服务器上的执行计划和索引都相同。
此 SELECT 语句在任何 SQL Server 2012 服务器(包括简单的开发计算机)上大约需要 50 毫秒。在任何 SQL Server 2014 服务器(包括真正强大的服务器)上,查询至少需要 1500 毫秒。
OPEN SYMMETRIC KEY MySymmetricKeyName
DECRYPTION BY CERTIFICATE MyCertificateName
SELECT CONVERT(int, DecryptByKey(article_id_enc))
FROM dbo.tblCertTest
关于为什么查询在 SQL Server 2014 上表现如此糟糕,有什么建议吗?发生了什么变化?
最佳答案
Edit: I just noticed that there is a KB article FIX: A query that uses the DECRYPTBYKEY function takes a long time in SQL Server 2014 but I have that installed and it doesn't appear to change the original conclusions below.
在运行 Windows 10 的四核 (Intel Core i5-2320) X64 桌面计算机上的 SQL Server 2012 (11.0.5343.0) 和 2014 (RTM) 中运行以下代码。
OPEN SYMMETRIC KEY MySymmetricKeyName DECRYPTION BY CERTIFICATE MyCertificateName;
DECLARE @B VARBINARY(100);
WITH t
AS (SELECT ROW_NUMBER() OVER (ORDER BY @@SPID) AS article_id
FROM sys.all_objects o1,
sys.all_objects o2,
sys.all_objects o3,
sys.all_objects o4)
SELECT @B = ENCRYPTBYKEY(KEY_GUID('MySymmetricKeyName'), CONVERT(VARBINARY(100), article_id))
FROM t
并在 Process Explorer 中查看它
2012
2014
有两件事立即变得显而易见。
2012 版本使用的 CPU 较少,并且最大限度地利用了单核。 2014 版本使用多个内核,并且内核模式事件显着增加(红色)
Process Explorer“线程”窗口显示
2012
单个线程独占调度程序。
2014
这里的工作由两个线程执行(线程 3212 正在运行空闲任务 sqldk.dll!SOS_Scheduler::Idle
)。
跟踪 2014 年进程显示 SQL Server 和这两个线程遇到了大量上下文切换(跟踪的时间与之前的屏幕截图不同,因此线程 ID 不同)
使用 Windows Performance Toolkit 跟踪两个进程显示不同模块所花费的时间存在显着差异
2012
2014
目前我不确定为什么 2014 版本在此 View 中报告 25% CPU,而在其他 View 中报告 30%,但无论如何,很明显,ntoskrnl.exe 花费的时间在不同版本之间急剧增加,现在为 60%时间花在该模块的代码上。执行加密所花费的时间当然也相应减少了。
附加 VS 代码分析器,2012 版本看起来像 this和 2014 年类似 this .
因此,2014 年似乎有额外的逻辑来阻止这种占用调度程序的情况,并且它会更频繁地关闭,如下面的附加项目所突出显示的那样。
(与2012年相比)
在两个版本中尝试以下操作来执行操作 100 万次...
SET STATISTICS TIME ON;
DECLARE @B VARBINARY(100);
OPEN SYMMETRIC KEY MySymmetricKeyName DECRYPTION BY CERTIFICATE MyCertificateName;
DBCC SQLPERF("sys.dm_os_wait_stats", CLEAR);
WITH t
AS (SELECT ROW_NUMBER() OVER (ORDER BY @@SPID) AS article_id
FROM master..spt_values v1,
master..spt_values v2
WHERE v1.type = 'P'
AND v2.type = 'P'
AND v1.number BETWEEN 1 AND 1000
AND v2.number BETWEEN 1 AND 1000)
SELECT @B = ENCRYPTBYKEY(KEY_GUID('MySymmetricKeyName'), CONVERT(VARBINARY(100), article_id))
FROM t
SELECT *
FROM sys.dm_os_wait_stats
WHERE wait_type IN ( 'PREEMPTIVE_OS_CRYPTOPS', 'SOS_SCHEDULER_YIELD' );
2012(CPU 时间 = 2344 毫秒,运行时间 = 2383 毫秒。)
可以清楚地看出,虽然 PREEMPTIVE_OS_CRYPTOPS
等待类型在 2012 年确实存在,但在本例中并未使用。
相反,它看起来好像查询或多或少地垄断了调度程序(尽管在 4 毫秒量子结束时仍然自愿屈服 - 4 * 597 = 2388)
2014(CPU 时间 = 8188 毫秒,运行时间 = 10569 毫秒。)
而在 2014 年,ENCRYPTBYKEY
函数的每次调用都会遇到这种等待类型,在这种情况下,它(与上下文切换相结合)使总运行时间增加了 8.2 秒。
下面突出显示了一些更耗时的内核调用的调用堆栈。
我还尝试了另一个实验
2014 - SQL Server 关联到单 CPU
(CPU 时间 = 4500 毫秒,运行时间 = 6648 毫秒。)
这里的时间介于 2012 年性能和 2014 年非关联性能之间,其中代码跨多个不同的内核执行。
关于sql-server - SQL Server 2014 上的 DECRYPTBYKEY 比 SQL Server 2012 慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29105290/