4

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

这可以通过在datetime列上进行聚类来实现:

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

    CONSTRAINT [IX_Things] UNIQUE CLUSTERED (CreatedDate)
)

但我不能保证两人Things不会有相同的时间。所以我的要求不能真正通过日期时间列来实现。

我可以添加一个虚拟身份 int列,并在其上进行聚类:

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

    CONSTRAINT [IX_Things] UNIQUE CLUSTERED (RowID)
)

但是您会注意到我的表格已经包含一timestamp列;保证单调递增的列。这正是我想要的候选集群键的特性。

所以我将表聚集在rowversion(aka timestamp) 列上:

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

    CONSTRAINT [IX_Things] UNIQUE CLUSTERED (timestamp)
)

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

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

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

4

4 回答 4

10

因此,我将表聚集在 rowversion(又名时间戳)列上:我没有添加虚拟标识 int 列 (RowID) 来确保顺序,而是使用我已经拥有的内容。

起初这听起来像是一个好主意 - 但它实际上几乎是你拥有的最糟糕的选择。为什么?

集群密钥的主要要求是(有关更多详细信息,请参阅Kim Tripp 的博客文章):

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

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

最后,对于您的情况,添加一个虚拟身份列可能是一个更好的选择。第二个最佳选择是datetime列 - 但是在这里,当出现重复时,您确实冒着 SQL Server 必须在条目中添加“唯一性”的风险 - 并且以 3.33 毫秒的精度,这肯定会发生 - 不是最佳的,但是绝对比这个rowversion主意好得多……

于 2010-04-21T19:01:05.860 回答
2

来自链接:timestamp在问题中:

时间戳语法已弃用。此功能将在 Microsoft SQL Server 的未来版本中删除。避免在新的开发工作中使用此功能,并计划修改当前使用此功能的应用程序。

可以使用 SELECT INTO 语句生成重复的 rowversion 值,其中 rowversion 列位于 SELECT 列表中。我们不建议以这种方式使用 rowversion。

那么,到底为什么要通过其中任何一个进行聚类,特别是因为它们的值在行更新时会发生变化?只需使用一个身份作为 PK 和集群就可以了。

于 2010-04-21T17:42:31.190 回答
1

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

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

CREATE CLUSTERED INDEX [IX_CreatedDate] ON .[Things] 
(
    [CreatedDate] ASC
)
于 2010-04-21T17:31:41.690 回答
0

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

于 2010-04-21T17:35:47.567 回答