SQL Server:按时间戳聚类;优点缺点

时间:2010-04-21 17:20:33

标签: sql-server timestamp clustered-index rowversion

我在SQL Server中有一个表,我希望将插入添加到表的末尾(而不是将它们插入中间的聚类键)。这意味着我希望表格由一些不断增加的列聚集。

这可以通过在datetime列上进行群集来实现:

CREATE TABLE Things (
    ...
    CreatedDate datetime DEFAULT getdate(),
    [timestamp] timestamp,        

    CONSTRAINT [IX_Things] UNIQUE CLUSTERED (CreatedDate)
)

但我不能保证两个Things不会有相同的时间。因此,日期时间列无法真正实现我的要求。

我可以添加一个虚拟 identity int列,并在其上添加群集:

CREATE TABLE Things (
    ...
    RowID int IDENTITY(1,1),
    [timestamp] timestamp,        

    CONSTRAINT [IX_Things] UNIQUE CLUSTERED (RowID)
)

但是你会注意到我的表已经在timestamp列;保证单调增加的列。这正是我想要的候选群集密钥的特征。

所以我将表格集中在rowversion(又名timestamp)列上:

CREATE TABLE Things (
    ...
    [timestamp] timestamp,        

    CONSTRAINT [IX_Things] UNIQUE CLUSTERED (timestamp)
)

我没有添加虚拟标识 int列(RowID)来确保订单,而是使用我已有的。

我正在寻找的是为什么这是一个坏主意的想法;以及其他更好的想法。

注意:社区维基,因为答案是主观的。

4 个答案:

答案 0 :(得分:8)

  

所以我将表格集中在   rowversion(又名时间戳)列:   而不是添加虚拟身份   int列(RowID)以确保订单,   我用我已经拥有的东西。

这可能声音一开始就是一个好主意 - 但它实际上几乎是你最糟糕的选择。为什么呢?

群集密钥的主要要求是(有关更多详细信息,请参阅Kim Tripp's blog post):

  • 稳定
  • 独特
  • 如果可能的话,不断增加

您的rowversion违反了稳定要求,这可能是最重要的要求。行的rowversion随着对行的每次修改而改变 - 并且由于您的聚类键被添加到表中的每个非聚集索引,因此您的服务器将不断更新非聚集索引的负载并浪费大量这样做的时间。

最后,添加虚拟标识列可能是您的案例的更好替代方案。第二个最佳选择是datetime列 - 但是在这里,您确实存在SQL Server必须在重复发生时为条目添加“唯一符号”的风险 - 并且准确度为3.33ms,这肯定会发生 - 不是最优的,但肯定比rowversion想法好得多......

答案 1 :(得分:2)

来自问题中的链接:timestamp

  

不推荐使用时间戳语法。   此功能将在a中删除   Microsoft SQL的未来版本   服务器。避免使用此功能   新的发展工作,并计划   修改当前使用的应用程序   这个功能。

  

可以使用重复的rowversion值   使用SELECT INTO生成   其中有一个rowversion列的语句   在SELECT列表中。我们不   建议在此使用rowversion   方式。

那么为什么你们想要通过它们进行聚类,特别是因为当行更新时它们的值会发生变化?只需使用身份作为PK和群集就可以了。

答案 2 :(得分:1)

你已经走上正轨了。您可以使用包含创建日期的DateTime列并创建 CLUSTERED但非唯一约束。

CREATE TABLE Things (
    ...
    CreatedDate datetime DEFAULT getdate(),
    [timestamp] timestamp,        
)

CREATE CLUSTERED INDEX [IX_CreatedDate] ON .[Things] 
(
    [CreatedDate] ASC
)

答案 3 :(得分:0)

如果此表获得大量插入,您可能会创建一个干扰更新的热点,因为所有插入都将发生在相同的物理/索引页面上。检查锁定设置。