最近在看这篇博文: 链接
其中包含本节:
选择聚集索引
有几种选择聚集索引的策略;最简单和最好的方法之一是添加另一列数据类型 datetime 并将该列用于聚集索引。这是您需要做的:
将列添加为数据类型 datetime
我通常称它为日期
将默认值设置为 GetDate()。
使其非空。
在向您插入数据之前,在其上创建聚集索引。
我的问题是这会为日期创建两个相同的值吗?如果使用并行性,这个答案会改变吗?(假设值从未指定,总是来自 GetDate())
我相信由于添加了幕后唯一性,我认为这无关紧要是正确的,对吧?但无论如何我都很感兴趣。
我是从 SQL2008R2 的角度询问的,但是如果从 7.0 开始的任何版本的 SQL Server 的答案都不同,我会感兴趣。
GETDATE()
不保证是唯一的,不。特别是如果它是一个日期时间,毫秒是向上或向下舍入的,当然当并非所有数据都来自同一个用户时,几乎肯定会发生冲突。当然,聚集索引不需要是唯一的,因为如果不是,SQL Server 会这样做(但仅在需要时)。如果您需要自己识别特定行(而不仅仅是 SQL Server 内部使用的唯一性),并且没有其他候选键列(这可能与事件日志表之类的东西),您可以添加一个非集群主键,即 IDENTITY 列。或者,如果您真的想要 Web 规模 - 并且更关心插入性能而不是存储或任何后续数据使用 - 您可以使用填充 NEWID() 的 uniqueidentifier 列。
例子
让我们看一个例子,看看有什么不同。
插入速度
我使用以下脚本填充了大约 500,000 行的所有三个表:
结果:
扫描速度
结果:
使用空间
查看来自以下的简单结果
sp_spaceused
:结果:
uniquifier 占用的空间比 IDENTITY 列少(显然两者都比 GUID 少),因为它仅用于碰撞(可能还有我不知道的其他优化,例如压缩)。
我们还可以查看日期时间列(索引 id = 1)和非聚集主键(索引 id = 2)上的聚集索引的索引页:
页/行内容
最后,我们可以查看特定页面以查看一行中存储的内容。我只是从上面的每个聚集索引 DBCC IND 结果中取出第一行(您的页面 id 值几乎肯定会不同):
Uniquifier - 特别注意长度/记录大小:
IDENTITY 似乎在聚集索引中有 4 个额外的字节:
GUID 在聚集索引中有额外的 16 个字节:
结论
在我看来,从各方面来说,你最好让 uniquifier 做自己的事情(假设你不希望能够区分具有完全相同日期/时间值的两行)。唯一一次您会遇到麻烦,如果任何单个值重复 2,147,483,648 次,此时您将溢出整数的唯一性范围。