使用INT或GUID作为主键

4

我试图在SQL Server和VB.net中创建一个ID列,用于为数据库中每个新行创建一个数字序列。因此,我使用了以下技术来创建ID列。

select * from T_Users
ALTER TABLE T_Users     
ADD User_ID INT NOT NULL IDENTITY(1,1) Primary Key

然后我将一些用户名注册到数据库中,它正常工作。例如,前六行的ID是1、2、3、4、5、6。然后第二天我又注册了4个用户,但这次ID从6跳到一个非常大的数字,例如:1、2、3、4、5、6、1002、1003、1004、1005。两天后,我再次注册两个用户,新的行号为3002、3004。所以我的问题是,为什么每隔一天注册用户时会跳过这么大的一个数字?我用来创建序列的技术有问题吗?如果有问题,请问有人可以告诉我正确的方法吗?当我对上述使用的技术感到沮丧时,我尝试使用顺序生成的GUID值。GUID值的序列生成得很好。然而,唯一的缺点是,它生成了一个非常长的数字(INT大小的4倍)。我的问题是,在使用GUID时是否有任何显着优势比INT更好?
此致,敬礼
2个回答

4

GUID的优点:

如果您想让离线客户端能够创建新记录,GUID非常有用,因为当新记录同步回主数据库时,您永远不会得到主键冲突。

GUID的缺点:

将GUID作为主键可能会对DB的性能产生影响,因为对于聚集主键, DB将希望按照键值的顺序保留行。但这意味着要在现有记录之间插入很多东西,因为GUID是随机的。

使用IDENTITY列不会遇到这个问题,因为下一条记录保证具有最高值,所以每次只需将行添加到末尾即可。不需要进行重新整理。

有一个妥协方案,那就是生成一个伪GUID,这意味着您可以预期每70年左右会发生一次关键冲突,但可以极大地帮助索引。

其他缺点是:a)它们需要更多的存储空间,b)编写SQL非常麻烦,例如键为50003的查询比键为'{F820094C-A2A2-49cb-BDA7-549543BB4B2C}'的查询要容易得多

您声明的IDENTITY列看起来不错。键值中的空白可能是由于尝试添加行失败导致的。IDENTITY值将被递增,但行不会提交。别太在意,几乎每个表都会发生这种情况。

编辑:

这个问题涵盖了我所指的伪GUID。INSERTs with sequential GUID key on clustered index not significantly faster

在SQL Server 2005+中,您可以使用NEWSEQUENTIALID()来获取一个随机值,该值应大于以前的值。有关更多信息,请参见此处http://technet.microsoft.com/en-us/library/ms189786%28v=sql.90%29.aspx


1
PK的技巧不在于对其进行聚类,而是在于对具有逻辑顺序的内容进行聚类,例如日期时间戳、名称等。 - Jon Egerton
DeanOC,感谢您的反馈。这对我很有帮助。 - A-Tech

-2
我用的创建序列的技术有问题吗?
不是。如果说有什么问题,那就是你的谷歌搜索技巧不够好。只要简单搜索“Sql server identity skipping values”,就会得到大量的搜索结果,包括: SQL Server 2012 column identity increment jumping from 6 to 1000+ on 7th entry 以及经典的: Why are there gaps in my IDENTITY column values? 你错误地认为 SQL Server 不会为了性能而优化其访问方式。标识号只是标记,没有任何假设它们之间没有间隔。
特别是:SQL Server 预分配 1000 个数字为一块,如果你重新启动服务器(比如在你的工作站上),剩余的数字就会丢失。

http://www.sqlserver-training.com/sequence-breaks-gap-in-numbers-after-restart-sql-server-gap-between-numbers-after-restarting-server/-

如果您手动进行序列(在新的 SQL Server 2012 中),则可以为此(预生成)定义缓存大小并将其设置为1,但在执行大量插入时会略微降低性能。

我的问题是使用 GUID 是否比 INT 有任何显着优势?

是的。使用 GUID 可以拥有比 int 更多的行。例如,int32 仅限于约20亿行。对于我们中的一些人来说,这太低了(我有10亿行的表),即使是64位的大整数也有限制。在一个真正的 zetabyte 数据库中,您必须使用自动生成的连续 GUID。

任何普通人都看不出区别,因为我们实际上并没有处理那么多行。而且更大的大小会使很多事情变慢(较大的键大小=索引中的更大空间=更大的索引=相同操作的更多内存/IO)。此外,即使您的顺序 ID 也会跳跃。

为什么不将您的期望调整为现实 - 身份证不应该没有间隙 - 或者使用缓存为1的序列。


3
放轻松,伙计!有比这个问题更糟的问题。 ;) - DeanOC
3
嗨TomTom,首先让我说声谢谢你的反馈。当我读到你的评论时,中途有点紧张,因为你描述的方式让我几乎想停止阅读。相信我,我确实谷歌搜索了好答案,但如果你没有用正确的词语搜索,你有时就找不到你要的答案。所以并不是我没有搜索过。因此,有时我们回答问题的方式可能会阻碍人们提问,这违背了像stackoverflow这样网站的目的。无论如何,还是谢谢你的帮助。 - A-Tech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接