SQL 服务器 - 比较大量 MD5 哈希值

SQL Server - Compare large number of MD5-Hashed Values

假设我在 SQL 服务器中有一个 table 存储客户电子邮件(几百万条记录)- 为简单起见,看起来如下所示:

CREATE TABLE [Emails]
(
    [Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [email] [nvarchar](1000) NOT NULL
)

我有一些客户向我发送他们客户电子邮件的列表,每个列表都有数百万条记录,但所有 MD5-Hash 都经过加密,因此列表看起来如下所示:

0x3B46E0E53842A74172BA678974E93BBB
0xACAC5843E184C85AA6FF641AAB0AA644
0xD3C7BA16E02BE75142761894E8E4A125
...

而且我必须想出一个快速的方法来查看我的 table 中存在他们列表中的哪些电子邮件。

根据我在网上/这里看到的一些答案,我想出了以下逻辑来做到这一点:

  1. 我创建了 Emails table 的索引视图,其中 MD5-Hash 列作为索引:

    CREATE VIEW dbo.vw_Emails
    WITH SCHEMABINDING
    AS
        SELECT 
            Id
             , email
             , CONVERT(VARBINARY(16), HASHBYTES('MD5', LOWER(email))) AS MD5
        FROM 
            dbo.Emails
    GO
    
    CREATE UNIQUE CLUSTERED INDEX Idx_vw_Emails ON vw_Emails (MD5)
    GO
    
  2. 我创建了一个存储过程,它将 BulkImport 给定的列表,将其转换为临时 table,根据我的观点加入它,并 return 任何匹配的行如下:

    CREATE PROCEDURE Import_ReturnMatches
    (
        @PathToCSVFile VARCHAR(8000)
    )
    
    AS
    
    DECLARE @fieldsep CHAR(1) = ',';
    DECLARE @recordsep CHAR(1) = CHAR(10);
    
    DECLARE @Emails TABLE 
    (
        MD5 VARCHAR(MAX) NOT NULL
    );
    
    DECLARE @sql VARCHAR(8000) = 
        'CREATE TABLE #tmp 
        (
              MD5 varchar(max) NOT NULL
        );
    
        BULK INSERT #tmp
        FROM ''' + @PathToCSVFile + '''
        WITH (FIRSTROW = 1, FIELDTERMINATOR = ''' + @fieldsep + ''', ROWTERMINATOR = ''' + @recordsep + ''');
    
        SELECT *
        FROM #tmp';
    
    INSERT INTO @Emails
    EXEC (@sql);
    
    SELECT 
        r.*
    FROM 
        @Emails l
        JOIN vw_Email_Dim r 
        ON l.MD5 = r.MD5
    

如您所见,我将导入的列类型设置为 VARCHAR(MAX),但这只是因为没有其他任何方法真正起作用...这就是我遇到的问题。它似乎总是 return 一个空集,即使我已经在我的文件中放置了应该匹配的记录。

我的问题是:

  1. 我做错了什么/我该如何解决?
  2. 我的存储/索引/导入是否使用了正确的数据类型?
  3. 这只是一个整体上的坏主意吗?是否有更好的方法来完成我想要做的事情?

您的问题可能是这个值:

LOWER(email)

如果您不确定使用何种大小写或编码(Windows 1252、UTF8、UTF16、UTF16LE?)从来源处的电子邮件生成 MD5 哈希值,那么您正在寻找需要测试所有组合的匹配哈希值。考虑我们在哪里将 LOWER 更改为 UPPER - 生成了一个完全不同的 MD5 哈希值:

您将需要控制如何在源中生成 MD5 哈希,或者将元数据(另一个字段)添加到导入中以描述输入的大小写和编码方式。

检查这个答案。您需要将 varchar 与 varchar 进行比较——我认为不是 varbinary。

Generate MD5 hash string with T-SQL