在现有表上将newid()更改为newsequentialid()

时间:2009-05-27 01:22:07

标签: sql clustered-index newsequentialid newid

目前我们有许多在主键上使用newid()的表。这导致大量碎片。所以我想将列更改为使用newsequentialid()代替。

我认为现有数据将保持相当分散,但新数据将更少碎片化。这意味着我可能需要等待一段时间才能将PK索引从非群集更改为群集。

我的问题是,有没有人有这方面的经验?有什么我忽略的,我应该小心吗?

4 个答案:

答案 0 :(得分:4)

您可能会考虑使用comb guids,而不是newsequentialid。

cast(
    cast(NewID() as binary(10)) +
    cast(GetDate() as binary(6))
as uniqueidentifier)

Comb guids是纯粹随机guid的组合以及当前日期时间的非随机性,因此连续几代梳状guid彼此靠近并且通常按升序排列。 Comb guids比newsequentialid有各种各样的优点,包括它们不是黑盒子的事实,你可以在默认约束之外使用这个公式,并且你可以在SQL Server之外使用这个公式。

答案 1 :(得分:3)

如果切换到sequentialguids 并且同时重新组织索引一次,则可以消除碎片。我不明白为什么你要等到碎片页链接在连续范围内重新排列。

话虽如此,您是否进行了任何测量以表明碎片实际上正在影响您的系统?只看一个索引并看到'碎片75%',暗示访问时间会受到影响。还有更多因素发挥作用(缓冲池页面预期寿命,读取与写入速率,顺序操作的位置,操作的并发性等)。虽然从guid切换到顺序guid通常是安全的,但您仍可能会引入问题。例如,您可以看到插入密集型OLTP系统的页面锁定争用,因为它会创建一个插入累积的热点页面。

答案 2 :(得分:0)

谢谢你,yfeldblum!您对COMB GUID的简单而简洁的解释确实帮助了我。我实际上正在考虑这篇文章的反面:我不得不放弃依赖newsequentialid(),因为我试图将SQL Server 2012数据库迁移到Azure,并且不支持newsequentialid()函数那里。

我能够使用以下语法将我的所有表PK默认值更改为COMB GUID:

ALTER TABLE [dbo].[Company] 
ADD  CONSTRAINT [DF__Company__Company_ID__72E6D332]  
    DEFAULT (CONVERT([uniqueidentifier],CONVERT([binary](10),newid(),0)+CONVERT([binary](6),getdate(),0),0)) FOR [CompanyId]
GO

我的SQL2012数据库现在很高兴地生活在Azure云中。

答案 3 :(得分:-4)

如果这是SQL Server,则通过调用newid()生成Guid。这对主键不好。使用主键的整数标识列,并使您的Guid成为代理键(和行guid列)。