【问题标题】:When using NEWSEQUENTIALID() as primary key, what should be my clustered index?当使用 NEWSEQUENTIALID() 作为主键时,我的聚集索引应该是什么?
【发布时间】:2020-10-08 13:36:47
【问题描述】:

我正在使用 newsequentialid 为表中的主键生成 GUID。

根据文档 (https://docs.microsoft.com/en-us/sql/t-sql/functions/newsequentialid-transact-sql?view=sql-server-ver15),不保证按顺序生成顺序 GUID。

重新启动 Windows 后,GUID 可以从较低的范围再次启动, 但仍然是全球唯一的

基本上,在您重新启动机器之前,它们都是有序的。

对于自动增量主键,将其作为聚集索引是有意义的,因为它保证插入的行将位于末尾。

对于 GUID 主键,将其作为聚集索引没有意义,因为它是随机的,插入的行不太可能位于末尾。

对于顺序 GUID 主键呢?主键应该是聚集索引,还是应该尝试查找另一列,如 DateCreated 字段?问题是像 DateCreated 这样的字段不会是唯一字段。如果我没有任何唯一字段,我应该将什么作为聚集索引?

【问题讨论】:

标签: sql sql-server newsequentialid


【解决方案1】:

对于聚集索引,顺序 GUID 比非顺序 GUID 更安全。通常,数据库不会特别频繁地重新启动。重启确实会导致页面分裂和碎片,但这通常不是太大的考虑因素,因为重启很少见。

也就是说,主键不需要是聚集索引键。您可以将 identity 列或创建日期/时间作为聚集索引,几乎可以消除此问题。

【讨论】:

  • 拥有另一个标识列基本上会破坏顺序 GUID 的主要优势之一,即能够轻松合并来自不同数据库的数据。在这种情况下,您可以将其用作主键。创建日期不是唯一的,因此将其设为聚集索引听起来像是不好的做法。但是,我同意你的看法——重启并不常见,所以唯一的影响是重启后第一次插入应该很慢。如果按时间顺序抓取数据很重要,我可以在 createddate 上放置一个非聚集索引。
  • “拥有另一个标识列基本上会破坏顺序 GUID 的主要好处之一” 是的,但 Gordon 是说将 IDENTITY 与非顺序 GUID 一起使用,不是顺序的,@Diskdrive。
  • @Diskdrive first insert after a reboot should be slow - 为什么它比任何其他需要新页面或可能添加到现有页面的插入要慢? SQL Server 不再需要任何时间来查找一个页面,该页面将容纳一个与重新启动前插入的最后一个键值不一致的键值。在任何情况下,一直以其他下游效应的潜在成本优化“重启后首次插入”的边缘情况似乎不是正确的路径。
  • @AaronBertrand - 不,你是对的 - 我认为我基本上不太了解聚集索引在后台的工作原理,因此我需要了解页面的工作原理等。
【解决方案2】:

不久前我写了一篇关于这个的长篇文章。 TL/DR 是使用顺序 GUID 作为聚集索引键很好。 GUID 实际上是插入到索引的中间,但是有少量(这里是一个)中间索引插入点不会导致昂贵的页面拆分或导致有害的碎片。

Good Page Splits and Sequential GUID Key Generation

同样的行为适用于使用复合键作为聚集索引,其中前导键列的基数较低。例如(客户 ID、交易 ID)。每个 CustomerId 将有一个半满的页面,其中包含下一个 TransactionId 的空间,当该页面填满时,会分配一个新页面。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-21
    • 2010-12-17
    • 2011-10-20
    • 2011-02-22
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 2012-12-30
    相关资源
    最近更新 更多