我正在尝试将表从使用guid主键/聚簇索引转换为使用int身份。这适用于SQL Server 2005.有两个表MainTable
和RelatedTable
,当前表结构如下:
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)
。
我希望我的转换可以做几件事:<
MainTable
更改为使用整数ID而不是GUID MainTableIDInt
列添加到链接到主表的整数ID RelatedTable
的主键和聚簇索引更改为(MainTableIDInt, SequenceNumber)
我写了一个脚本来执行以下操作:
IDInt int IDENTITY
添加MainTable
列。这会进行表重建并生成新的标识ID值。MainTableIDInt int
列添加到RelatedTable
。下一步是为每一行填充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
“显示估计执行计划”显示两个查询大致相同。它吐出的执行计划如下:
MainTable
和RelatedTable
并对其进行合并加入[估计行数= 4亿] RelatedTable
[估计行数= 4亿] 我很关心这个[排序4亿行听起来不愉快]的表现。我对这些执行计划的执行情况的担忧是否合理?是否有更好的方法来更新我的相关表的新ID,该ID将根据表的大小进行缩放?
答案 0 :(得分:1)
首先,这将是一个令人头痛的问题。其次,在我有数据之前,我不会更改任何索引或约束。即,我将添加标识列,但不将其作为主键或聚簇索引。然后我将把即将出现的新外键添加到各种表中。您的查询应如下所示:
Update ChildTable
Set NewIntForeignKeyId = P.NewIntPrimaryKey
From ChildTable As C
Join ParentTable As P
On P.PrimaryKey = C.ForeignKey
首先,请注意我正在使用内连接。鉴于您最终将在新列之间强制实施参照完整性,因此没有理由对此类查询使用外部联接。其次,如果首先填充列然后重建约束,那么它将更快,因为您将能够利用现有索引。请记住,更改聚簇索引时,它会重建所有非聚簇索引。如果表格很大,那将是一个严重的打击。
一旦有了数据,我就会删除所有主要约束,唯一约束,外键约束和唯一索引。最后删除聚集索引/约束。然后,我将聚簇索引添加到所有表中,之后完成,重新创建唯一约束,外键约束和索引。如果在重新创建聚簇索引之前未删除现有索引,它将重建现有索引两次:一次删除聚簇索引时,再次重新创建它时。
顺便说一下,我非常怀疑有一种方法可以避免表格扫描,因为你要更新每一行。