【问题标题】:SQL Server database with clustered GUID PKs - switch clustered index or switch to sequential (comb) GUIDs?具有聚集 GUID PK 的 SQL Server 数据库 - 切换聚集索引或切换到顺序(梳状)GUID?
【发布时间】:2010-04-09 08:51:33
【问题描述】:

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

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

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

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

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

谢谢!

【问题讨论】:

    标签: sql-server guid uniqueidentifier clustered-index


    【解决方案1】:

    我的意见很明确:使用 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 中作为群集键不好的优秀系列:

    马克

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • 感谢您的回答。只是快速评论/澄清:我不关心 GUID 的可猜测性,只关心它们在安装中的唯一性。
      • 然后,只需将您的 guid 更改为 SQL Server 中的 NEWSEQUENTIALID() 等顺序 guid,即可解决您的大部分直接问题。但是,不要推迟对身份进行全面重构。
      • 因此,鉴于我们选择了顺序 GUID:如果客户在许多表中拥有 100K 行,那么这样的变化是否会使他们受益,或者情况会像今天一样糟糕,因为表和索引已经充满了“随机”数据?
      • 一旦您重建索引,情况就会有所改善,并且将使用顺序 guid 进行后续插入。见stackoverflow.com/questions/170346/…
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-30
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      • 2010-09-25
      • 2012-11-28
      相关资源
      最近更新 更多