更改数据类型大型活动表

Shr*_*nal 5 sql-server

我在 SQL Server 2008 R2 中有一个表,其中包含接近 10 亿行的复合 PK 列。我想将列的数据类型从日期更改为日期时间。两次 ALTER TABLE zzz ALTER COLUMN yyy 有效,但速度很慢。我怎样才能加快这个过程?我想将数据复制到另一个表、删除、创建、复制回并切换到简单恢复模式或以某种方式使用游标一次 1000 行执行此操作,但我不确定这些是否真的会导致任何改进。

Tho*_*ser 12

概括

对于大型表,移动数据而不是更改表几乎总是可取的。要获得最大速度,请使用以下模式之一。让我们调用您要更改的表S(对于源)。

  1. 创建一个空副本S。让我们称之为T
  2. ALTER TABLET。这非常快,因为T没有行
  3. 如果T有一个簇索引,删除所有其他索引,但簇
  4. 如果T是堆,删除所有索引
  5. 将数据库置于 SIMPLE 恢复模式(如果可以,但要注意备份影响)
  6. 使用下面复制数据部分中提供的两个选项之一
  7. 重建索引 T
  8. 删除S并重命名为T

复制数据

在上面的第 6 步中,您需要以尽可能高的速度从S到移动数据T。以下是两个选项:

  1. INSERT ... SELECT
  2. 使用 SSIS

在这两者中,SSIS 是最快的。与INSERT ... SELECT您仅限于单个线程。然而,INSERT ... SELECT要容易得多。请参阅下面的更多细节。

选项 1:插入...选择

如果T是堆,请执行以下操作:

INSERT INTO T WITH (TABLOCK) SELECT ... FROM S
Run Code Online (Sandbox Code Playgroud)

这是最低限度的记录。

如果T有聚集索引,请执行以下操作:

DBCC TRACEON (610)
INSERT INTO T SELECT ... FROM S
Run Code Online (Sandbox Code Playgroud)

这也是最低限度的记录。此选项的问题在于您只能INSERT并行运行一个语句。因为 SQL Server 不执行并行INSERT ... SELECT,这将您限制在大约 40-80MB/秒 - 这很慢。

选项 2:使用 SSIS

这个选项比较麻烦,但也比较快。这个想法是这样的:

  1. 删除所有索引 T
  2. 创建一个 SSIS 包,该包采用一个参数来选择行的子集S(使用索引支持的某些过滤器)。SSIS 包然后将行移动到在批量模式下T使用TABLOCK提示
  3. 执行 SSIS 包的多个副本,每个副本都在自己的不同子集上运行S(因此您不会在 中重复行T

这要快得多,因为包可以并行运行。使用这种技术,我通常可以以 GB/秒的速度移动表。


gbn*_*gbn 0

无论哪种方式有效,都取决于您的维护窗口。

对于较大的表,我更喜欢重复表方法,因为它可以缓解锁定/维护窗口问题。

我也会使用 50000 或 100000 的批量大小