我正在为我公司正在启动的新数据库制定数据库标准。 我们试图定义的一件事是与唯一标识符相关的主键和聚集索引规则。
(注意:我不想讨论使用唯一标识符作为主键或聚集索引的利弊。 网络上有大量关于这方面的信息。 这不是那个讨论。
所以这是让我担心的情况:
假设我有一个表,其中唯一标识符作为聚集索引和主键。 让我们称之为可乐。 我将 ColA 的默认值设置为 NewSequentialId((。
使用该 NewSequentialId(( 我插入三个连续行:
{72586AA4-D2C3-440D-A9FE-CC7988DDF065}
{72586AA4-D2C3-440D-A9FE-CC7988DDF066}
{72586AA4-D2C3-440D-A9FE-CC7988DDF067}
然后我重新启动我的服务器。 NewSequentialId 的文档说:"重新启动 Windows 后,GUID 可以从较低的范围重新启动,但仍然是全局唯一的。
因此,下一个起点可以低于上一个范围。
因此,重新启动后,我又插入了 3 个值:
{35729A0C-F016-4645-ABA9-B098D2003E64}
{35729A0C-F016-4645-ABA9-B098D2003E65}
{35729A0C-F016-4645-ABA9-B098D2003E66}
(我不确定 guid 在数据库中的确切表示方式,但让我们假设由于这个以 3 开头,而前面的以 7 开头,因此 3 个比 7 个"小"。
在聚集索引中间执行插入操作时,必须重新映射索引。 (至少我的DBA是这么告诉我的。 每次重新启动时,我都会冒着使新的唯一标识符范围位于其他先前范围的中间的风险。
所以我的问题是:由于下一组唯一标识符将小于上一组,每次插入都会导致我的聚集索引随机播放吗?
如果没有,为什么? SQL Server 是否知道我正在使用 NewSequentialId? 它如何弥补这一点吗?
如果没有,那么它怎么知道我接下来要插入什么? 也许接下来的百万次插入将从 3 开始。 或者也许他们会从 7 开始。 它怎么知道?
或者它不知道,只是让一切井井有条。 如果是这种情况,那么一次重新启动可能会极大地影响性能。 (这让我觉得我需要自己的自定义 NewSequentialId,它不受重启的影响。 这是对的吗? 还是有什么我不知道的魔法?
编辑:在我的标准中,强烈建议不要将GUID作为聚集索引。 正如我上面所说,有很多原因表明这是一个坏主意。 我试图找出这是否是另一个原因。
您将使用适当的FILL FACTOR
创建索引,以便在所有页面中为这种情况留出空白空间。 话虽如此,一旦空白空间被填满,聚集索引就会被重新排序。
我知道您不想讨论使用 GUID
作为集群键,但这是不推荐的做法的原因之一。
将发生的情况是,您将拥有越来越多的页面拆分,这将导致您不断插入行时非常高水平的碎片,并且您需要以更高的频率重建索引以保持性能一致。
对于该主题的完整处理,没有比
金
特里普的
博客
作为旁注,当您考虑创建自己的 NewSequentialID 创建函数时,您可能会遇到设计问题,应该重新考虑您的计划。