在主键/聚集索引中使用全局唯一标识符(GUID)

8

我对SQL Server性能有一定了解,但我经常需要反驳GUID应该作为集群主键的默认类型的想法。

假设表每天插入的行数相当低(5000个左右/天),我们可能会遇到什么样的性能问题?页面分裂会如何影响我们的查找性能?我应该多久重新索引一次(或者应该碎片整理)?我应该将填充因子设置为多少(100、90、80等)?

如果我每天插入100万行呢?

我很抱歉提出这么多问题,但我希望得到一些支持不使用GUID作为PK的备选方案。然而,我完全愿意接受StackOverflow用户基础的压倒性知识来改变我的想法。


也许是 https://dev59.com/70fRa4cB1Zd3GeqP9HJF 的重复问题? - Matt Hamilton
非常相似,但我正在寻找一些具体的东西——可以用于未来的问题解决者。 - NTDLS
4个回答

8

如果你正在处理大量数据,使用GUID作为主键是非常糟糕的选择,除非你使用连续的GUID,原因正如您所描述的那样。 页面碎片化非常严重

                 Average                    Average
                 Fragmentation  Fragment    Fragment   Page     Average 
Type             in Percent     Count       Size       Count    Space Used

id               4.35           7           16.43      115      99.89
newidguid        98.77          162         1          162      70.90 
newsequentualid  4.35           7           16.43      115      99.89

正如这个与GUID和整数的比较所示:

在插入完成后运行DBCC SHOWCONTIG,Test1造成了大量页面分裂,并且扫描密度约为12%。而Test2表格的扫描密度约为98%。

然而,如果你的数据量非常低,那么这并不重要。

如果你确实需要一个全局唯一ID,但数据量很高(不能使用顺序ID),只需将GUID放入索引列中即可。


这个播客包含了一次关于非顺序GUID作为主键的问题的良好讨论。http://www.dotnetrocks.com/default.aspx?showNum=455。 - Rex Miller
抱歉重新提起这个问题,但上面的链接已经失效了。 - zer09

2

使用GUID作为主键的缺点:

  • 没有有意义的顺序,这意味着索引不像整数那样提供性能提升。
  • GUID的大小为16字节,而整数的大小为2、4或8字节。
  • 对人类来说非常难记,因此不适合用作参考ID。

优点:

  • 允许非可猜测的主键,因此在网页查询字符串或应用程序中显示时更安全。
  • 在数据库不提供自动增量或标识数据类型时非常有用。
  • 在需要在两个不同的数据源之间跨平台或环境联接数据时非常有用。

我认为是否使用GUID的决定非常简单,但也许我不知道其他问题。


1
GUID在数据集或部分数据集需要从不同来源合并时作为ID非常重要。 - Rex M
在以前的公司:我们运行儿童保育网络服务,许多公司都在单独的数据库中,正在合并和收购彼此。首席开发人员决定使用GUID作为PK,这使得公司的合并非常简单。然而,由于无法通过LoadRunner的基准测试(索引扫描/搜索占用100%的CPU),该公司最终倒闭了。性能极差... - NTDLS
@NTDLS,是的,通常我不会将非聚集索引设置为GUID,但在这种情况下创建另一个列作为GUID,并在其上使用聚集索引是可以的。 - Ash
抱歉,我之前的评论中“聚集”和“非聚集”是反过来的。 - Ash

1

考虑到每天的插入量如此之低,我怀疑页面分裂是否应该是一个重要因素。真正的问题是5,000与现有行数相比如何,因为这将是决定适当的初始填充因子以推迟分裂所需的主要信息。

话虽如此,我个人不太喜欢GUID。我知道它们在某些情况下可以很好地发挥作用,但在许多情况下,它们只会“妨碍”[效率、易用性等]。

我认为以下问题有助于缩小决定是否使用GUID的范围。

  • PK是否会被共享/发布?(即它是否会在SQL内部使用之外被使用,应用程序是否需要这些键以某种持久的方式?用户是否会看到这些键?
  • PK是否可用于帮助合并不同的数据源?
  • 表中是否有由数据列组成的主键-可能是复合主键?这个可能的键的大小是多少?
  • 主键如何排序?如果是复合的,前几列是否具有选择性?

0

使用 GUID 作为聚集索引(除非它是顺序 GUID)会降低插入性能。由于物理表布局根据聚集索引对齐,使用具有随机排序的 GUID 将导致严重的表碎片化。如果您想将 GUID 用作 PK/Clustered 索引,则必须使用 SQL Server 中的 newsequentialid() 函数生成顺序 GUID。这将确保生成的 GUID 按顺序排序并防止碎片化。


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