Sql Server 中如何加快向大表添加列的速度

Chr*_*ris 11 sql-server

我想向大约有 10M 行的 Sql Server 表添加一列。我认为这个查询最终会完成添加我想要的列:

alter table T
add mycol bit not null default 0
Run Code Online (Sandbox Code Playgroud)

但它已经持续了几个小时。是否有任何快捷方式可以将“非空默认 0”列插入到大表中?或者这本质上真的很慢?

这是 Sql Server 2000。稍后我必须在 Sql Server 2008 上做类似的事情。

Mar*_*son 9

嗯,10M 行是相当少的,但它并不超出 MSSQL 的范围,而且看起来确实很慢。

我们有一个行大小(设计不佳)和超过 10M 行的表。当我们不得不修改结构时,它是def。非常慢,所以我们所做的是(保持表格在线,从记忆中这是很粗糙的,因为它是很久以前的):

  • 创建后缀为“C”(用于转换)和新结构(即与旧表相同,但具有新列/索引/等)的新表
  • SELECT * INTO tableC FROM table
  • sp_rename 'table' 'tableOld'
  • sp_rename 'tableC' 'table'

这样,转换需要多长时间都没有关系,因为旧数据在线。这可能会导致在转换发生时将行写入表的问题(这对我们来说不是问题,因为数据每天只写入一次,但每小时查询数千次)所以你可能想要调查.


KPW*_*INC 7

根据您的行大小、表大小、索引等,我已经看到 SQL Server 2000 在最终完成之前运行了几个小时(4-5 小时)。

您现在可以做的最糟糕的事情是“恐慌”并努力杀死它。让它自己跑出来。

将来,您可能希望尝试执行 Farseeker 提到的操作并创建第二个(空)结构并通过这种方式复制您的记录。

  • 表格行越长,花费的时间就越长。
  • 该表上的索引越多,所需的时间就越长。
  • 如果您添加默认值(您这样做了),则需要更长的时间。
  • 如果您在服务器上大量使用,则需要更长的时间。
  • 如果您不锁定该数据库或将其置于单用户模式,则需要更长的时间。

当我不得不做这样难看的事情时,我会尝试在晚上做……比如凌晨 2 点,没有人在做(并且维护不在服务器上运行)。

祝你好运!:-)


Chr*_*ter 7

您可以尝试在单独的批处理中执行操作的每个步骤,例如

alter table T add mycol bit null
go
update T set mycol = 0
go
alter table T alter column mycol bit not null
go
alter table T add default 0 for mycol
go
Run Code Online (Sandbox Code Playgroud)

优点是:

  • 您可以获得关于操作进度的更好反馈,因为现在是 4 个独立的批次,每个批次大约需要 1/4 的时间。
  • 它降低了从客户端代码运行时出现超时错误的可能性。
  • 我发现它有时会提高性能。

您还可以尝试在进行更改之前删除表上的所有非聚集索引,然后再恢复它们。添加一列很可能涉及大规模的页面拆分或其他低级别的重新排列,并且您可以在进行时无需更新非聚集索引的开销。


mrd*_*nny 5

这将需要相当长的时间。这是因为您正在添加默认值。这会导致 SQL Server 更新单个事务中的所有行。确保没有其他人正在使用该表,因为这会导致您的进程阻塞。