newid() 和 newsequentialid() 有什么区别/优缺点?

36
在所有主键都是GUID的数据库中,使用newid()和newsequentialid()作为“默认值或绑定”的区别、影响以及优缺点是什么?
据我所知,它们唯一的区别在于newid()创建一个随机的新GUID,而newsequentialid()会基于表中的最后一个GUID按增量方式创建一个新的GUID。
4个回答

35

当您在数据库中插入一行时,将按照相对于表中其他主键的顺序进行插入。使用普通的GUID,它可能位于表中任何位置。使用newsequentialid()将始终添加到表的末尾。

因此,插入操作的性能得到了提高。

这个网站解释了两种不同方法之间的差异和基准测试。

更新-参考的博客文章已经移动。链接现在指向一个web.archive.org链接。以下是关键要点:

enter image description here

最引人注目的是NEWID系统函数所需的写入次数。 这与平均页面密度69%相结合,证明了由于插入在叶级别上的随机分布而引起的页面拆分。 一旦页面填满,就需要将其拆分为两个50%的页面才能完成插入。 页面拆分不仅导致页面密度较低,而且使数据页面非常分散(下一个数据页面与当前页面不相邻的概率为99%)。 在我们的测试中,为页面拆分所需的空闲页面最有可能位于表的末尾,而不管插入行的位置在哪里。 因此,要按顺序读取行,扫描需要在广泛分布的拆分页面之间来回跳跃,因此碎片化情况极其严重。

-- Stefan Delmarco


什么?如果它们是按顺序生成的,如何保证生成的GUID实际上是唯一的,而不仅仅是看起来像GUID的东西? - Justin
6
@Justing - 并不能完全保证GUID是唯一的,但它通常是唯一的。请注意,此翻译并未更改原文意思。 - Hans Kesting
1
链接是不稳定的...Fotia现在已经使答案中的链接返回404。 - Marc L.
3
http://web.archive.org/web/20110526141832/http://www.fotia.co.uk/fotia/DY.19.NewSequentialId.aspx - RoboJ1M

14

关于使用顺序键(如identity、sequence和NEWSEQUENTIALID)与非顺序键(如NEWID或自定义随机键生成器)的问题,需要考虑几个方面。

首先看顺序键,所有行都进入索引的右端。当一页满了时,SQL Server分配一个新页并填充它。这样可以减少索引的碎片化,有助于提高读取性能。而且,如果单个会话正在加载数据且数据驻留在单个驱动器或少数驱动器上,则插入速度可能更快。

然而,在使用拥有多个卷轴的高端存储子系统时,情况可能不同。当从多个会话加载数据时,您将在索引叶级别的链接列表的最右侧页面中遇到页面闩锁争用(闩锁是用于同步访问数据库页面的对象)。这个瓶颈阻止了存储子系统的全吞吐量的利用。

请注意,如果您决定使用顺序键,并且使用数字键,则始终可以从类型的最小值开始使用整个范围。例如,在INT类型中,您可以从-2,147,483,648开始,而不是从1开始。

考虑非顺序键,例如使用NEWID或自定义解决方案生成的随机键。当试图将行强制添加到已满页面时,SQL Server执行经典的页面拆分-它分配一个新页面,并将原始页面中一半的行移动到新页面中。页面拆分是有成本的,并且会导致索引碎片化。索引碎片化可能对读取性能产生负面影响。然而,在插入性能方面,如果存储子系统包含许多卷轴并且您正在从多个会话加载数据,则随机顺序实际上可以比顺序更好,尽管存在拆分。

这是因为索引右端没有热点,并且您可以利用存储子系统的全吞吐量。

可用吞吐量更佳。一个展示这种策略的良好基准测试示例可以在 Thomas Kejser 的博客中找到,链接为:http://blog.kejser.org/2011/10/05/boosting-insert-speed-by-generating-scalable-keys/

来源: 查询 Microsoft® SQL Server® 2012考试70-461 培训套件


1
据我理解,当SQL实例启动时,NEWSEQUENTIALID GUID会被初始化为一个随机值。然后,在其操作期间,GUID将在中央GUID上递增,而不是通过查看表生成的最后一个GUID。

1
这样做的好处在于索引。完全随机的GUID会使索引过于分散,而顺序GUID对于插入和索引性能是有益的。 - Todd
微软公司表示,自上次启动主机以来生成的最后一个GUID是顺序的。 - Lars Gyrup Brink Nielsen

-5
据我所知,NEWID() 以随机顺序生成 GUID,而NEWSEQUENTIALID() 则按顺序生成 GUIDNEWSEQUENTIALID() 只能在表的默认子句中使用。

6
你没有在问题中添加任何东西。 - Dale K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接