转换为身份ID时如何更新guid ID引用

时间:2010-06-24 00:01:50

标签: sql-server guid identity

我正在尝试将表从使用guid主键/聚簇索引转换为使用int身份。这适用于SQL Server 2005.有两个表MainTableRelatedTable,当前表结构如下:

MainTable [4000万行]

IDGuid - uniqueidentifier - PK
-- [data columns]

RelatedTable [4亿行]

RelatedTableID - uniqueidentifier - PK
MainTableIDGuid - uniqueidentifier [foreign key to MainTable]
SequenceNumber - int - incrementing number per main table entry since there can be multiple entries related to a given row in the main table. These go from 1,2,3... etc for each MainTableIDGuid value.
-- [data columns]

MainTable的聚集索引当前是主键(IDGuid)。 RelatedTable的聚集索引目前为(MainTableIDGuid, SequenceNumber)

我希望我的转换可以做几件事:<

  1. MainTable更改为使用整数ID而不是GUID
  2. MainTableIDInt列添加到链接到主表的整数ID
  3. 的相关表
  4. RelatedTable的主键和聚簇索引更改为(MainTableIDInt, SequenceNumber)
  5. 摆脱guid列。
  6. 我写了一个脚本来执行以下操作:

    1. IDInt int IDENTITY添加MainTable列。这会进行表重建并生成新的标识ID值。
    2. MainTableIDInt int列添加到RelatedTable
    3. 下一步是为每一行填充RelatedTable.MainTableIDInt列及其相应的MainTable.IDInt值[基于匹配的guid ID]。这是我挂断的一步。我知道这不会很快,但我希望它能尽可能好地发挥作用。

      我可以写一个执行此更新的SQL语句:

      UPDATE RelatedTable
      SET RelatedTable.MainTableIDInt = (SELECT MainTable.IDInt FROM MainTable WHERE MainTable.IDGuid = RelatedTable.MainTableIDGuid)
      

      UPDATE RelatedTable
      SET RelatedTable.MainTableIDInt = MainTable.IDInt
      FROM RelatedTable 
      LEFT OUTER JOIN MainTable ON RelatedTable.MainTableIDGuid = MainTable.IDGuid
      

      “显示估计执行计划”显示两个查询大致相同。它吐出的执行计划如下:

      1. 群集索引扫描MainTableRelatedTable并对其进行合并加入[估计行数= 4亿]
      2. 排序[估计行数= 4亿]
      3. 群集索引更新RelatedTable [估计行数= 4亿]
      4. 我很关心这个[排序4亿行听起来不愉快]的表现。我对这些执行计划的执行情况的担忧是否合理?是否有更好的方法来更新我的相关表的新ID,该ID将根据表的大小进行缩放?

1 个答案:

答案 0 :(得分:1)

首先,这将是一个令人头痛的问题。其次,在我有数据之前,我不会更改任何索引或约束。即,我将添加标识列,但不将其作为主键或聚簇索引。然后我将把即将出现的新外键添加到各种表中。您的查询应如下所示:

Update ChildTable
Set NewIntForeignKeyId = P.NewIntPrimaryKey
From ChildTable As C
    Join ParentTable As P
        On P.PrimaryKey = C.ForeignKey

首先,请注意我正在使用内连接。鉴于您最终将在新列之间强制实施参照完整性,因此没有理由对此类查询使用外部联接。其次,如果首先填充列然后重建约束,那么它将更快,因为您将能够利用现有索引。请记住,更改聚簇索引时,它会重建所有非聚簇索引。如果表格很大,那将是一个严重的打击。

一旦有了数据,我就会删除所有主要约束,唯一约束,外键约束和唯一索引。最后删除聚集索引/约束。然后,我将聚簇索引添加到所有表中,之后完成,重新创建唯一约束,外键约束和索引。如果在重新创建聚簇索引之前未删除现有索引,它将重建现有索引两次:一次删除聚簇索引时,再次重新创建它时。

顺便说一下,我非常怀疑有一种方法可以避免表格扫描,因为你要更新每一行。