SQL SERVER:BCP 使用数据库密钥导入和加密列

SQLSERVER: BCP import and encrypt columns using Database Key

我有一个大文件需要导入到 SQL 服务器。文件包含个人信息列(如 first_name、phone_number)。目前我正在使用 BCP 工具将大文件导入 SQL 服务器。下一步,我将使用数据库密钥对列进行加密,如下所示。

CREATE TABLE users (
    first_name VARCHAR(4000)
)

CREATE CERTIFICATE db_cert1
WITH SUBJECT = 'Encrypt PII data'; 
GO 

CREATE SYMMETRIC KEY db_symkey1
WITH ALGORITHM = AES_256
ENCRYPTION BY CERTIFICATE db_cert1;
GO

BEGIN TRY
    UPDATE users
    SET first_name = CAST(EncryptByKey(KEY_GUID('db_symkey1'),[first_name]) AS VARCHAR(MAX))
END TRY
BEGIN CATCH
    DELETE FROM users;
END CATCH

我的 table 中有 100 列和 10 列需要加密的敏感列和数百万行。目前它很慢(由于行数和 VARCHAR(MAX/4000))

有没有更好的方法来实现这个? BCP 是否提供开箱即用的解决方案?

由于您的字段类型,我猜您正在执行转换为 nvarchar(max)。使用 varbinary 会更好。

函数EncryptByKeyreturns:

varbinary with a maximum size of 8,000 bytes.

因此,以这种格式存储您的数据将消除转换的需要。此外,最好使用 varbinary 长度的精确值。

您可以使用下面的公式来检查 EncryptByKey 将 return 用于特定文本列的最大 varbinary 长度:

60 + max_length - ((max_length + 8) % 16) 

我经常使用以下脚本:

SELECT name,  60 + max_length - ((max_length + 8) % 16) 
FROM sys.columns
WHERE object_id = OBJECT_ID('dbo.securityUsers')
    AND name in ('FirstName', 'LastName', 'Gender', 'Address1', 'Address2', 'City', 'Province', 'Country')

例如,对于 nvarchar(128),您将有 varbinary(308)。你只需要有一些方法来知道当你解密时,再次转换为 nvarchar(128)

一般来说,尽量使用尽可能小的精度的类型,并尽量转换到尽可能小的精度。

例如,您可以将这些数据插入缓冲区 table,然后将其加密并记录在目标 table 中(无需转换)。

以下是提高性能所遵循的步骤。

  1. 为每个敏感数据创建了两列
    • first_name_plaintext VARCHAR(256)
    • first_name VARBINARY(308)
    • 感谢@gotqn
  2. 添加了一个自动递增的 id 列,在 table 上添加了一个聚集索引(这确保它已经排序)并进行了批量更新(如 WHERE [id] BETWEEN 1 AND 100000)。
  3. 每次迭代后提交(以减少事务日志的使用)
  4. 将数据库恢复模型更改为简单(重要)
  5. 增加了数据库文件大小
  6. 如果没有限制,您可以使用 AES_128 加密来创建密钥而不是 AES_256,但我们的安全顾问不允许这样做。

这将 100 万条记录的时间从 3 分钟缩短到 1:17 分钟。