【问题标题】:sql server 2008 newsequentialid() problemsql server 2008 newsequentialid() 问题
【发布时间】:2009-04-10 20:40:56
【问题描述】:

我在 sql server management studio 中遇到 newsequentialid() 学习问题。创建一个包含唯一标识符列“UniqueID”的表,并将默认值设置为 newsequentialid()。

步骤 1. 保存设计:

'Table_1' 表 - 验证列“UniqueID”的默认值时出错。

还是保存吧。

第二步,查看sql:

CREATE TABLE [dbo].[Table_1](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
    [UniqueID] [uniqueidentifier] NOT NULL
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Table_1] ADD  CONSTRAINT [DF_Table_1_UniqueID]  DEFAULT (newsequentialid()) FOR [UniqueID]
GO

看起来很合理。

第 3 步。添加一些行:

1    test    72b48f77-0e26-de11-acd4-001bfc39ff92
2    test2    92f0fc8f-0e26-de11-acd4-001bfc39ff92
3    test3    122aa19b-0e26-de11-acd4-001bfc39ff92

它们看起来不是很连续。 ??

编辑:如果插入全部一次完成,我已经让它工作了一些,那么唯一 id 是连续的。在以后的插入中,sql server 似乎忘记了最后的顺序 id,并开始一个新的序列。

在 ssms 中运行它会产生 squential guid:

insert into Table_1 (Name) values('test13a');
insert into Table_1 (Name) values('test14a');
insert into Table_1 (Name) values('test15a');
insert into Table_1 (Name) values('test16a');
insert into Table_1 (Name) values('test17a');

【问题讨论】:

  • newsequentialid() 是从哪里来的?
  • 这是一个糟糕的函数名。 GUID 不是连续的,而是单调递增的。对于这种类型的 guid,47 个字节是 MAC 地址,16 个是时钟周期,60 位是自 1582 年 10 月 15 日以来的时间,增量为 100 纳秒。如果您好奇,可以查看 RFC 4122 的第 4.2 节。
  • 值不是按 GUID 的文本表示排序,而是按内部二进制值排序 ~ Pro SQL Server 2008 关系数据库设计和实现第 628 页唯一标识符

标签: sql-server


【解决方案1】:

newsequentialid 主要是为了解决当你的表被一个唯一标识符聚集时的页面碎片问题。您的表由整数列聚集。我设置了两个测试表,一个是 newsequentialid 列是主键,另一个不是(像你的那样),并且在主键中 GUID 总是顺序的。另一方面,他们不是。

我不知道内部/技术原因为什么它会这样,但很明显 newsequentialid() 只有在你的表被它聚集时才是真正的顺序。否则,它的行为似乎类似于 newid() / RowGuid。

另外,我很好奇为什么你会在不需要时使用 newsequentialid()。它有许多 newid() 没有的缺点,也没有任何好处 - 最大的是 newid() 实际上不可预测,而 newsequentialid() 是。如果不担心碎片化,那还有什么意义呢?

【讨论】:

  • 不是 100% 像 newid()。如果一次完成多个插入,则 id 是连续的。
  • @Paul 当我在非聚集列上使用 newsequentialid() 一次尝试多次插入时,创建的 ID 是相同的。
  • 即使对于聚集索引,newsequentialid() 也不是真正 100% 遵循“顺序性”——一些插入批次可能会起作用,但最终,它会跳到一组新的 GUID .尽量避免使用 GUID——尤其是作为集群键——无论如何!
  • @marc_s 你有关于“序列”重置的任何文档吗?
  • @Rex :我刚刚在两个示例中尝试过 - 上面的 table_1,在 GUID 列上带有聚集索引的 table_2 - 在任何一种情况下,序列都不是真正连续的。
【解决方案2】:

根据 NEWSEQUENTIALID() 的 the definition,这些值实际上是“连续的”:

创建一个大于任何 GUID 之前生成的 GUID 此函数在 Windows 启动后的指定计算机上运行。

并不是说 GUID 中不能有任何间隙,只是任何新的 GUID 都应该大于前一个。

试试这个:

create table #test(id int, txt varchar(50), gid uniqueidentifier)

insert into #test
select 1    ,'test','72b48f77-0e26-de11-acd4-001bfc39ff92'
union select 2,    'test2', '92f0fc8f-0e26-de11-acd4-001bfc39ff92'
union select 3,    'test3', '122aa19b-0e26-de11-acd4-001bfc39ff92'

select * from #test
order by gid asc

如您所见,记录按 1、2、3 顺序排列,这与预期一致。

【讨论】:

    【解决方案3】:

    它们是连续的!

    1    test     72b48f77-0e26-de11-acd4-001bfc39ff92
    2    test2    92f0fc8f-0e26-de11-acd4-001bfc39ff92
    3    test3    122aa19b-0e26-de11-acd4-001bfc39ff92
    

    77

    【讨论】:

      【解决方案4】:

      我不熟悉 newsequentialid(),对于 uniqueidentifier 类型我称之为 newid()。

      【讨论】:

      • newsequentialid 用于解决在uniqueidentifier上聚类时页面碎片的问题:msdn.microsoft.com/en-us/library/ms189786.aspx
      • SQL Server 2008 联机丛书 NEWSEQUENTIALID() (Transact-SQL)
      • 感谢您的信息:)。否决票有点苛刻,但也许这应该是一个评论。
      • 我认为这个答案并没有为这个特定的讨论增加任何价值,但既然你让我对此感到内疚,我会把它拉回来:)
      • 不怪那些提供信息的人。也没有任何责备,真的。每个人都有权发表自己的意见,否则,拥有一个社区有什么意义?
      【解决方案5】:

      NewSequentialId() 序列中肯定存在空白 - 我发现以下导致空白的原因:

      1. 只要另一个需要 NewSequentialId() 的表进行另一个调用
      2. 插入失败
      3. 回滚

      (2和3在这方面类似于identity())

      例如,给定 2 个表,使用 NewSequentialId()

      create table XXX(someGuid uniqueidentifier DEFAULT NEWSEQUENTIALID(), x INT)
      create table YYY(someGuid uniqueidentifier DEFAULT NEWSEQUENTIALID(), y DateTime)
      GO
      
      insert into XXX(x) values(1)
      insert into XXX(x) values(2)
      insert into XXX(x) values(3)
      GO
      insert into YYY(y) values(current_timestamp)
      insert into YYY(y) values(current_timestamp)
      insert into YYY(y) values(current_timestamp)
      GO
      insert into XXX(x) values(4)
      insert into XXX(x) values(5)
      insert into XXX(x) values(6)
      GO
      
      SELECT * FROM XXX
      6A6E85CB-CCA3-E111-9E8E-005056C00008    1
      6B6E85CB-CCA3-E111-9E8E-005056C00008    2
      6C6E85CB-CCA3-E111-9E8E-005056C00008    3
      **CCEA7AF2-CCA3-E111-9E8E-005056C00008  4** Gap here because we 'switched' to y
      CDEA7AF2-CCA3-E111-9E8E-005056C00008    5
      CEEA7AF2-CCA3-E111-9E8E-005056C00008    6
      
      SELECT * FROM YYY
      8F9438E1-CCA3-E111-9E8E-005056C00008    2012-05-22 07:13:35.503
      909438E1-CCA3-E111-9E8E-005056C00008    2012-05-22 07:13:41.210
      919438E1-CCA3-E111-9E8E-005056C00008    2012-05-22 07:13:41.220
      

      此外,在插入失败的情况下,NewSequentialId() 不会返回到序列中,例如

      insert into XXX(x) values(1)
      insert into XXX(x) values(2)
      BEGIN TRAN
      insert into XXX(x) values(3)
      insert into XXX(x) values(4)
      ROLLBACK TRAN
      insert into XXX(x) values(5)
      insert into XXX(x) values(6)
      GO
      
      686EFE5B-CDA3-E111-9E8E-005056C00008
      696EFE5B-CDA3-E111-9E8E-005056C00008
      6C6EFE5B-CDA3-E111-9E8E-005056C00008
      6D6EFE5B-CDA3-E111-9E8E-005056C00008
      
      i.e. a Gap of 2 Guids rolled back
      
      and
      
      insert into XXX(x) values(1)
      insert into XXX(x) values(2)
      insert into XXX(x) values(3)
      GO
      insert into XXX(x) values(99999999999999) -- overflow
      GO
      insert into XXX(x) values(4)
      insert into XXX(x) values(5)
      insert into XXX(x) values(6)
      go
      
      select * from xxx
      AC613611-CFA3-E111-9E8E-005056C00008    1
      AD613611-CFA3-E111-9E8E-005056C00008    2
      AE613611-CFA3-E111-9E8E-005056C00008    3
      **B0613611-CFA3-E111-9E8E-005056C00008  4** Gap of 1 - overflow failure
      B1613611-CFA3-E111-9E8E-005056C00008    5
      B2613611-CFA3-E111-9E8E-005056C00008    6
      

      【讨论】:

      • 您说的是“间隙”,但间隙并不一定意味着它不是连续的。
      • @Rex M 我很挑剔。尽管新的 ID 总是增加并因此解决了碎片问题,但它们不一定在每个表的基础级别(如身份)上是连续的。您在数学上是正确的,因为序列不需要是连续的(或递增的,或就此而言是唯一的),但大多数读者会将“连续”这个词与增量相关联。我试图为 OP 提供出现“非相邻连续”序列的其他情况。
      【解决方案6】:

      NEWSEQUENTIALGUID(以保证其顺序的方式生成的每个 guid)包括通过时间戳计算的 Guid 的一部分。因此,如果您在不同的时间运行插入,您会看到一些间隙。

      但重要的部分是 Guid 以不会导致页面拆分的方式“排序”(如果 Guid 用于索引中),这就是使用新的顺序 guid 时发生的情况。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多