5

我们有一个数据库,其中所有的 PK 都是 GUID,大多数 PK 也是表的聚集索引。我们知道这很糟糕(由于 GUID 的随机性)。因此,这里似乎基本上有两种选择(没有将 GUID 作为 PK 完全丢弃,这是我们不能做的(至少目前不是))。

  • 我们可以将 GUID 生成算法更改为例如 NHibernate 使用的算法,如本文所述或者
  • 对于使用最频繁的表,我们可以更改为不同的聚集索引,例如 IDENTITY 列,并将“随机”GUID 保留为 PK。

在这种情况下是否可以给出任何一般性建议?

有问题的应用程序有 500 多个表,目前最大的一个大约有 150 万行,一些表大约 500 000 行,其余的则显着减少(其中大多数远低于 10K)。

此外,该应用程序已经安装在多个客户站点,因此我们必须考虑对现有客户可能产生的任何负面影响。

谢谢!

4

2 回答 2

7

我的意见很明确:使用 INT IDENTITY 作为集群键。这是迄今为止最好、最优化的聚类键,因为它:

  • 小的
  • 稳定(不应该改变)
  • 独特
  • 不断增加

顺序 GUID 肯定比常规随机 GUID 好得多,但仍然比 INT 大四倍(16 对 4 字节),如果表中有很多行和很多非聚集索引,这将是一个因素也在那张桌子上。集群键被添加到每个非聚集索引中,因此显着增加了 16 字节与 4 字节大小的负面影响。更多字节意味着磁盘和 SQL Server RAM 中的页面更多,因此更多的磁盘 I/O 和更多的 SQL Server 工作。

在适当的情况下,您绝对可以将 GUID 保留为主键 - 但在这种情况下,我强烈建议向该表添加单独的 INT IDENTITY 并将该 INT 作为集群键。我自己用一些大表完成了这项工作,结果令人惊讶——表碎片从 99% 和更多的百分比下降到几个百分比,并且性能要好得多。

查看 Kimberly Tripp 关于为什么 GUID 在 SQL Server 中作为集群键不好的优秀系列:

马克

于 2010-04-09T08:57:16.750 回答
3

如果您能够轻松地将您的 guid 生成更改为顺序 guid 生成,那么这可能是您快速获胜的选择。顺序 guid 将停止表上的碎片,同时保留为您的聚集索引。不过,顺序 guid 的主要缺点是它们变得可猜测,这通常是不希望的,也是首先使用 guid 的原因。

如果你沿着你的聚集主键的身份路线走,然后只是你的 guid 列上的一个索引,那么你的 guid 索引上仍然会有很多碎片。然而,表格将不再碎片化的事实将是一个巨大的收获。

最后,我知道您说您现在不能这样做,但是,如果您根本不需要使用 guid 作为索引,那么您可以消除所有这些问题。

于 2010-04-09T09:03:04.850 回答