使用MD5 Hash作为主键与使用int标识作为SQL Server主键的优缺点

时间:2014-05-20 04:02:39

标签: sql sql-server database hash

我有一个应用程序来处理文件并将其分段到多个段,然后将结果保存到sql server数据库中。有许多重复的文件(可能有不同的文件路径),所以首先我浏览所有这些文件并计算每个文件的Md5哈希,并使用[Duplicated]列标记重复的文件。

然后每天,我将运行此应用程序并将结果保存到[Result]表中。 db模式如下:

    CREATE TABLE [dbo].[FilePath]
    (
        [FilePath] NVARCHAR(256) NOT NULL PRIMARY KEY,
        [FileMd5Hash] binay(16) NOT NULL,
        [Duplicated] BIT NOT NULL DEFAULT 0, 
        [LastRunBuild] NVARCHAR(30) NOT NULL DEFAULT 0
    )

    CREATE TABLE [dbo].[Result]
    (
        [Build] NVARCHAR(30) NOT NULL,
        [FileMd5Hash] binay(16) NOT NULL , 
        [SegmentId] INT NOT NULL,
        [SegmentContent] text NOT NULL 
        PRIMARY KEY ([FileMd5Hash], [Build], [SegmentId])
    )

我要求在FileMd5Hash上加入这两个表。

由于[Result]的行数非常大,我想添加一个int Identity列来将它们连接到表中,如下所示:

    CREATE TABLE [dbo].[FilePath]
    (
        [FilePath] NVARCHAR(256) NOT NULL PRIMARY KEY,
        [FileMd5Hash] binay(16) NOT NULL,
        **[Id] INT NOT NULL IDENTITY,**
        [Duplicated] BIT NOT NULL DEFAULT 0, 
        [LastRunBuild] NVARCHAR(30) NOT NULL DEFAULT 0
    )

    CREATE TABLE [dbo].[Result]
    (
        [Build] NVARCHAR(30) NOT NULL,
        **[Id] INT NOT NULL,**  
        [SegmentId] INT NOT NULL,
        [SegmentContent] text NOT NULL 
        PRIMARY KEY ([FileMd5Hash], [Build], [SegmentId])
    )

那么这两种方式的优点和缺点是什么?

3 个答案:

答案 0 :(得分:11)

int键更易于实现,更易于使用和理解。它也更小(4个字节对16个字节),因此索引大约是每个IO页面条目数的两倍,这意味着更好的性能。表格行也会更小(好,不会小很多),所以你每页还要适合更多的行=更少的IO。

哈希总是会产生碰撞。尽管极为罕见,但正如birthday problem所示,随着记录数增加,碰撞变得越来越可能。与各种比特长度哈希发生碰撞的几率为50%所需的项目数量如下:

Hash length (bits)   Item count for 50% chance of collision
                32   77000
                64   5.1 billion
               128   22 billion billion
               256   400 billion billion billion billion

还有必须传递非ascii字节的问题 - 更难调试,通过线路发送等。

为表使用int个连续主键。其他人都这样做。

答案 1 :(得分:3)

对主键使用int,而不是哈希。每个人都警告哈希碰撞,但在实践中它们不是一个大问题;它很容易检查冲突和重新哈希。如果合并数据库,顺序ID也会发生冲突。

哈希作为键的一个大问题是您无法更改数据。如果您尝试,您的哈希将更改并且所有外键都将变为无效。你必须在你的数据库中创建一个“不,这是真正的哈希”列,你的旧哈希就会成为一个很大的非顺序整数。

我打赌你的业务分析师会说“我们实施WORM,所以我们的记录永远不会改变”。他们将被证明是错误的。

答案 2 :(得分:1)

这是一篇非常好的文章,解释了使用两者的优点和缺点:

http://databases.aspfaq.com/database/what-should-i-choose-for-my-primary-key.html

使用MD5哈希就像使用主键的GUID一样。哈希碰撞很少发生,但确实发生了,你可能想要处理它。

我将亲自使用INT IDENTITY,但可能会因您的实施而有所不同。