我的 SQL 服务器 CLR 功能很慢

My SQL Server CLR function is very slow

我在 C# 中创建了两个方法:

public static string Encrypt(string clearText, string encryptionKey)
{
        byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);

        using (Aes encryptor = Aes.Create())
        {
            var pdb = new Rfc2898DeriveBytes(encryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
            encryptor.Key = pdb.GetBytes(32);
            encryptor.IV = pdb.GetBytes(16);

            using (var ms = new MemoryStream())
            {
                using (var cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(clearBytes, 0, clearBytes.Length);
                    cs.Close();
                }

                clearText = Convert.ToBase64String(ms.ToArray());
            }
        }

        return clearText;
    }

    public static string Decrypt(string cipherText, string encryptionKey)
    {
        try
        {
            byte[] cipherBytes = Convert.FromBase64String(cipherText);

            using (Aes encryptor = Aes.Create())
            {
                var pdb = new Rfc2898DeriveBytes(encryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                encryptor.Key = pdb.GetBytes(32);
                encryptor.IV = pdb.GetBytes(16);

                using (var ms = new MemoryStream())
                {
                    using (var cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(cipherBytes, 0, cipherBytes.Length);
                        cs.Close();
                    }

                    cipherText = Encoding.Unicode.GetString(ms.ToArray());
                }
            }
        }
        catch (Exception)
        {
        }

        return cipherText;
    }

按照 This Link 中给出的步骤,我在 SQL 服务器中创建了一个 CLR 函数,我试图这样调用它:

SELECT dbo.Decrypt(MyEncrypted, EncryptionKey)
FROM   MyTable

问题是,它花费了太多时间。就像只有 1000 行一样,花了 1.5 分钟。如果我在没有 CLR 函数的情况下调用我的查询,它花费的时间不到 1 秒。

我可以做些什么来提高 CLR 函数的性能吗?

我已经用 VS2010 中的性能分析器分析了你的 Decrypt 方法 运行 100 次:

如您所见,GetBytes method of the Rfc2898DeriveBytes 实例花费的时间最多。

我不确定您为什么有这些特定的 encryption/decryption 要求,但影响 GetBytes 方法所用时间的一种方法是使用 [=21= 实例化 Rfc2898DeriveBytes ] 以迭代作为第三个参数。默认值为 1000,我可以将其设置为低至 1。但强烈建议反对

var pdb = new Rfc2898DeriveBytes(encryptionKey, salt, 10);  

对于 EncryptDecrypt,此迭代确实需要相同,因此如果您想更改它,则必须 Decrypt\Encrypt 当前值。

另一种选择可能是像 this answer 中推荐的那样缓存 IV 值。如果他们在那里谈论使用相同的密钥,我还不够专家,但如果这是一个选项,您也可以缓存对 GetBytes 的调用以获取密钥。

所有描述的更改都会影响您的数据加密方式和加密强度。在测试解决方案时考虑这两种影响。