我有一个应用程序来处理文件并将其分段到多个段,然后将结果保存到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])
)
那么这两种方式的优点和缺点是什么?
答案 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,但可能会因您的实施而有所不同。