当使用 NEWSEQUENTIALID() 作为主键时,我的聚簇索引应该是什么?

When using NEWSEQUENTIALID() as primary key, what should be my clustered index?

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

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

After restarting Windows, the GUID can start again from a lower range, but is still globally unique

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

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

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

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

对于聚集索引,顺序 GUID 比非顺序 GUID 安全得多。一般来说,数据库重启的频率不是特别高。重启确实会导致页面分裂和碎片化,但这通常不是一个太大的考虑因素,因为重启很少见。

也就是说,主键不必是聚簇索引键。您可以使用 identity 列或创建 date/time 作为聚簇索引,几乎可以消除此问题。

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

Good Page Splits and Sequential GUID Key Generation

同样的行为也适用于使用复合键作为聚集索引,其中前导键列具有较低的基数。例如 (CustomerId,TransactionId)。每个 CustomerId 将有一个半满页面,其中 space 用于下一个 TransactionId,当该页面填满时,将分配一个新页面。