【问题标题】:SQL Server : uniqueidentifier type Inserting Before Old Rows After Reboot, How to Prevent?SQL Server:重启后在旧行之前插入唯一标识符类型,如何防止?
【发布时间】:2012-08-12 02:36:34
【问题描述】:

我有一个使用uniqueidentifier 作为聚集主键的SQL Server 表。创建表并插入几行后,我重新启动了服务器。该列使用NEWSEQUENTIALID() 作为其默认值。

但是,在重新启动后,下一次插入创建了一个 GUID 值低于之前值的行,导致它出现在 SELECT * 语句的顶部。

我的问题:在使用 GUID 类型的聚集主键时,有什么方法可以防止洗牌(AKA 保留行的顺序)?

【问题讨论】:

  • 简而言之:没有。这些 GUID 充其量是伪顺序的,而且最肯定的是在 SQL Server 服务停止并重新启动之后,就不再有任何保证了。无论如何,作为 PK 的 GUID 是一个非常糟糕的选择 - 我会研究 INT IDENTITY,它在性能方面要好得多,并且这些值由 SQL Server 保证,并且会不断增加 - 即使在服务器重新启动后也是如此。
  • 这里有描述(可能还有数百个其他地方,这只是第一个有用的搜索结果):sqltrends.blogspot.com/2011/04/…
  • 无订单。没有什么可订购的,因为它是一个用户帐户列表,只有用户名和 oauth 令牌。但是,仍然首选时间顺序。
  • 没有ORDER BYTOP (x) 是毫无意义的——你得到what 前10 行?如果它们不是按某些东西排序的 - 你希望看到哪 10 行??
  • @marc_s 插入的前 10 行(添加的最早的 10 个帐户)。

标签: sql sql-server indexing guid uniqueidentifier


【解决方案1】:

如果要保证时间顺序,请添加一个名为CreatedDate 的列,将其设置为不允许NULL,并将默认设置为CURRENT_TIMESTAMP。然后要获取最后 10 行,您可以说:

SELECT TOP 10 (*) FROM dbo.foo ORDER BY CreatedDate DESC;

这样你的TOP 就有意义了。没有ORDER BY,正如marc 解释的那样,你的TOP 毫无意义,虽然结果是相对可预测的(它们不是很随机,我更喜欢“任意”这个词),但它们不会有任何可靠性以它们插入的相同顺序进行排序。无论您使用 GUID 还是整数作为主键都是如此 - 不能保证。

你永远无法保证使用NEWSEQUENTIALID() 保留订单,抱歉,这不是它的工作原理。

【讨论】:

    【解决方案2】:

    文档说它会生成一个新的 guid,保证是在 windows 启动后完成的最后一个之后。

    在其中放置一个添加日期的列,用于订购,只需使用 newid 作为您的 guid。它不仅可以工作,还可以为您提供更多信息,并且完全清楚正在发生的事情,更不用说它会使您的设计更便携。

    【讨论】:

    • 而带有newid() 的 GUID 对于 PK 来说甚至是一个非常糟糕的选择 .... but that's a totally different story ....
    • 我自己尽量避免,太稀疏而没有效率。 BigInt 主键作为代理项和 Guid 作为跨分布式数据扩展的唯一键是一种更好的方法。除此之外,我什至不会依赖 bigint 来指示数据的顺序,太容易在没有意识到的情况下破坏隐含的规则。
    猜你喜欢
    • 2018-10-05
    • 2012-05-14
    • 1970-01-01
    • 1970-01-01
    • 2014-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-23
    相关资源
    最近更新 更多