【问题标题】:Change column types in a huge table更改大表中的列类型
【发布时间】:2012-05-25 12:43:47
【问题描述】:

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

【问题讨论】:

  • 您能解释一下您将数据类型从什么更改为什么吗?
  • 我看不出如何使用光标来更改列类型?列类型是对表中所有值的更改。
  • 创建一个新列,复制游标中的数据,删除旧列,重命名新列。不知道这是否有效。
  • 我认为您提供的Alter 声明是您最好的选择。

标签: sql sql-server sql-server-2008 sql-server-2008-r2


【解决方案1】:

根据您所做的更改,有时进行维护窗口会更容易。在该窗口期间(没有人应该能够更改表中的数据),您可以:

  1. 删除所有指向旧列的索引/约束,并禁用触发器
  2. 添加一个具有新数据类型的新可为空列(即使它本应为 NOT NULL)
  3. 更新新列,将其设置为旧列的值(您可以在单个事务的块中执行此操作(例如,使用 UPDATE TOP (10000) ... SET newcol = oldcol WHERE newcol IS NULL 一次影响 10000 行)并使用 CHECKPOINT 以避免超出日志)
  4. 完成更新后,删除旧列
  5. 重命名新列(并在适当时添加 NOT NULL 约束)
  6. 重建索引和更新统计数据

这里的关键是它允许您在第 3 步中逐步执行更新,而您不能在单个 ALTER TABLE 命令中执行此操作。

这假设该列在数据完整性方面没有发挥主要作用 - 如果它涉及一堆外键关系,则有更多步骤。

编辑

另外,我只是想知道,我还没有对此进行任何测试(但将其添加到列表中)。我想知道页面+行压缩是否会有所帮助?如果将 INT 更改为 BIGINT,则在适当的压缩后,SQL Server 仍应将所有值视为仍然适合 INT。同样,我还没有测试这是否会使更改更快或更慢,或者首先添加压缩需要多长时间。直接扔了。

【讨论】:

  • 数据库将离线。将恢复模式设置为简单有帮助吗?
  • 在 SIMPLE 或 FULL 中,巨大的 ALTER TABLE 命令不会有任何不同,因为在这两种情况下都会记录整个内容。综上所述,SIMPLE 可能会好一些,但如果您选择合适的批量大小,恢复模型应该无关紧要。此外,如果数据库“离线”(我假设您不是指 ALTER DATABASE...SET OFFLINE),为什么速度很重要?以上可能会节省一些时间,但速度不会快得惊人。你所做的只是需要时间。
  • 亚伦,感谢您的帮助。速度很重要,因为使用此数据库的网站只会离线几个小时。
  • @Gordon ALTER TABLE ... ADD 可为空的列应该是一个元数据操作,并且应该非常快 - 我不会将其限定为与“通过表”相同的级别。此外,如果您复制整个表格,您将移动更多的数据而不仅仅是 int 列。如果您有约束、外键、它会弄乱依赖项等,更改表也可能非常复杂。我认为在现有表中工作不会给您带来太多收益。
  • @user1417408 好的,如果源列可以为空,那么WHERE newcol IS NULL AND oldcol IS NOT NULL...
【解决方案2】:

如果您使用的是 SQL Server Management Studio 之类的工具,您只需转到数据库中的表,右键单击,选择“设计”,然后选择要编辑的列:将其设置为 bigint 并点击保存。更改整个列,但之前的值将保持不变。这对于允许表“从”int 到 bigint 是有好处的,但据我所知不会更改现有数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-27
    • 2019-06-27
    • 2013-09-12
    • 1970-01-01
    • 2019-03-09
    • 2021-07-24
    • 2011-09-11
    • 2010-11-02
    相关资源
    最近更新 更多