简体   繁体   中英

My SQL Server CLR function is very slow

I have created two methods in 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;
    }

By following the steps given in This Link , I have created a CLR function in SQL Server and I am trying to call it like:

SELECT dbo.Decrypt(MyEncrypted, EncryptionKey)
FROM   MyTable

The problem is, it is taking TOO MUCH TIME . Like for only 1000 rows, it took 1.5 minutes. If I call my query without the CLR function, it took less than 1 second.

Is there any thing I can do to improve the performance of the CLR functions?

I've analyzed your Decrypt method with the Performance Analyzer in VS2010 by running it 100 times:

最热的路径是GetBytes

As you can see the GetBytes method of the Rfc2898DeriveBytes instance take the most time.

I'm not sure why you have these specific encryption/decryption requirements but one way influence the time the GetBytes method takes is to instantiate the Rfc2898DeriveBytes using the constructor that takes iterations as the third parameter. Default it is on 1000, I can set it as low as 1. BUT THIS IS STRONGLY ADVISED AGAINST

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

This iterations does need to be the same for both the Encrypt and Decrypt so you'll have to Decrypt\\Encrypt your current values if you want to change that.

One other option might be to cache the IV values as seems to recommended in this answer . I'm not enough of an expert if they talk there about using the same Key as well but if that is an option you might cache the call to GetBytes for the key as well.

All the described change have impact on how your data is encrypted and the strength of your encryption. Consider both impacts when testing the solutions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM