【问题标题】:DECRYPTBYKEY slower on SQL Server 2014 than SQL Server 2012SQL Server 2014 上的 DECRYPTBYKEY 比 SQL Server 2012 慢
【发布时间】:2015-05-20 05:56:27
【问题描述】:

几年来,我们一直在使用对称密钥对一些 SQL Server 2012 实例进行加密/解密。我们最近安装了一些新的 SQL Server 2014 实例,在解密 SQL Server 2014 安装数据时遇到了一些性能问题。

考虑一个如下所示的表格:

CREATE TABLE [dbo].[tblCertTest](
[article_id_enc] [varbinary](100) NOT NULL,
[article_id] [int] NULL
) ON [PRIMARY]

以及像这样创建的密钥和证书:

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 上执行如此糟糕的任何建议?有什么变化?

【问题讨论】:

    标签: sql-server encryption sql-server-2012 database-performance sql-server-2014


    【解决方案1】:

    编辑:我刚刚注意到有一篇知识库文章FIX: A query that uses the DECRYPTBYKEY function takes a long time in SQL Server 2014,但我已经安装了它,它似乎并没有改变下面的原始结论。

    在运行 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 版使用的不仅仅是一个内核,而且内核模式活动明显更多(红色)

    进程资源管理器“线程”窗口显示

    2012

    单个线程独占调度器。

    2014

    这里的工作由两个线程执行(线程 3212 正在运行空闲任务sqldk.dll!SOS_Scheduler::Idle)。

    跟踪 2014 年的进程显示 SQL Server 和这两个线程遇到了很多上下文切换(跟踪时间与之前的屏幕截图不同,因此线程 ID 不同)

    使用 Windows Performance Toolkit 跟踪这两个进程显示在不同模块中花费的时间存在一些显着差异

    2012

    2014

    目前我不确定为什么 2014 版本在此视图中报告的 CPU 为 25%,而在其他视图中为 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 年非关联性能之间,其中代码跨多个不同内核执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-11
      • 2014-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-02
      • 2014-09-22
      • 1970-01-01
      相关资源
      最近更新 更多