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

Posted

技术标签:

【中文标题】SQL Server:按时间戳聚类;优点缺点【英文标题】:SQL Server: Clustering by timestamp; pros/cons 【发布时间】:2011-02-10 17:19:01 【问题描述】:

我在 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)来确保订单,而是使用我已经拥有的。

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

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

【问题讨论】:

时间戳将是一个非常糟糕的主意,因为每当更新行时它就会更新! 这是 MS SQL 吗?如果是这样,聚簇索引不必是唯一的,因此只需将其从约束中删除即可。 @Martin Smith:哦,该死的,我忘了!你应该把它放在一个答案中,所以我可以接受它作为“哦,上帝不要这样做”。 @Chris Hass:如果聚集索引未标记为唯一,SQL Server 将添加另一个 4 字节“唯一符”。当 8 字节时间戳已经唯一时,每行再浪费 4 字节是没有意义的。 @Ian Boyd,前提是您没有在其他地方声明唯一索引,对吧? 【参考方案1】:

所以我将表格聚集在 rowversion(又名时间戳)列: 而不是添加一个虚拟身份 int 列(RowID)以确保顺序, 我使用我已有的。

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

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

稳定 窄 独一无二的 尽可能增加

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

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

【讨论】:

+1 为答案。你的答案应该有另一个+1的开头句;它的措辞非常完美,可以吸引读者。而且它委婉而有礼貌。【参考方案2】:

来自链接:timestamp 在问题中:

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

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

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

【讨论】:

rowversiontimestamp 的新名称。我特别决定使用术语timestamp,因为更多的人会知道我在说什么。但两者是相同的。只有在插入重复的rowversions 时,才能插入重复的rowversions。实际上没有人这样做。最后,你最后的丢弃声明是一个正当的理由:它们会随着更新而改变,这会打乱行。【参考方案3】:

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

【讨论】:

从 SQL Server 7.0 开始,热点真的不再是大问题了 当然,这不是什么大问题,但如果他想将所有插入内容强制插入表格的一小部分,则需要注意。 真正的重点是我不想通过 newid() uniqueidentifier 进行聚类。出于同样的原因,我不想按其他值进行聚类。【参考方案4】:

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

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

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

【讨论】:

以上是关于SQL Server:按时间戳聚类;优点缺点的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server的优点与缺点

excel与sql server各自的优点与缺点

SQL Server 的优点都有哪些。

聚类算法使用小结

機器學習聚类算法使用小结

数据库SQL SERVER 2008 R2 时间戳如何转换成时间格式