如何添加一列到大型SQL Server表(How do I add a column to larg

2019-09-02 08:14发布

我在生产具有数百万行的SQL Server表,而且事实证明,我需要一列添加到它。 或者,更准确,我需要一个字段添加到该表代表的实体。

在语法上这不是一个问题,如果表中没有那么多的行,并没有在生产中,这将是很容易。

真的就是我后的行动方针。 有很多的网站,在那里有非常大的表,而且必须添加字段不时。 他们如何做没有实质性的停工?

有一件事我要补充,我不想列允许空值,这将意味着我需要有一个默认值。

所以,我要么需要弄清楚如何使用默认值及时添加一列,或者我需要找出一种方法来更新在稍后的时间列,然后设置列不允许为空。

Answer 1:

ALTER TABLE table1 ADD
  newcolumn int NULL
GO

不应该花那么长...什么需要很长的时间来插入其他列的中间列... B / C则引擎需要创建一个新表,并将数据复制到新表。



Answer 2:

连续运行时间,唯一的解决方法就是冗余

我承认@内斯特的回答,添加新列不应该采取长期在SQL Server中,但尽管如此,它仍然可能是一个中断,是不是在生产系统上可以接受的。 另一种方法是使并行系统的变化,那么一旦操作完成后,换了新的历史。

例如,如果你需要添加一列,您可以创建表的副本,然后将列添加到该副本,然后用sp_rename()到旧桌子放在一边,新表移动到位。

如果你有指向该表参照完整性约束,这样可以使交换更加棘手。 你可能有你换表简要删除约束。

对于一些各种复杂的升级,你可以完全复制一个单独的服务器主机上的数据库。 一旦准备好了,只是换了两台服务器,瞧DNS条目!

我在1990年谁在任何时候都奔三台的重复数据库服务器支持的证券交易所上市的公司。 这样,他们可以实现在一台服务器上的升级,同时保留一个生产服务器和一台故障转移服务器。 他们的操作必须通过生产,故障转移和维护的角色,每天旋转三台机器的标准程序。 当他们需要升级硬件,软件或更改数据库架构,它花了三天时间通过传播他们的服务器的变化,但他们可以在不中断服务的做到这一点。 感谢所有冗余。



Answer 3:

“添加列,然后执行相对小批量更新填充有默认值的列。这应该防止任何明显的减速”

在这之后,你必须设置列到NOT NULL,这将在一个大的交易火了。 所以一切都将运行非常快,直到你做,那么你有可能获得很少真的。 我只知道这个从第一手经验。

您可能希望当前的表从X重命名为Y中,您可以使用此命令sp_RENAME“[OldTableName]”,“[NewTableName]”做到这一点。

重新创建新表与设置为与Y NOT NULL,然后批量插入到X新列X,包括您在插入新列的默认值或者或放置一个默认值就当你重建表X的新列

我已经做了这种类型的变化对表有数亿行的。 它仍然花了一个多小时,但它并没有打击我们的反式日志。 当我试图只是改变列NOT NULL与表中的所有数据用了20多天前我杀的过程。

你测试的只是添加一列数据填充它和列设置为NOT NULL?

那么到底,我不认为有什么灵丹妙药。



Answer 4:

我不想列允许空值,这将意味着我需要有一个默认值。

添加NOT NULL与列DEFAULT约束到任意数量的行(甚至数十亿)的表成为在SQL Server中容易得多 ,从2012年(但仅限于企业版),因为它们允许它是一个在线操作(在大多数情况下, )其中,对于现有的行,该值将来自元数据被读取并没有实际存储在行中,直到行被更新,或聚簇索引重建。 而不是意译更多,这里是从为MSDN页面的相关部分ALTER TABLE :

添加NOT NULL列的联机操作

使用SQL Server 2012企业版开始,加入了NOT NULL列有默认值时的默认值是运行时常联机操作。 这意味着,操作完成几乎瞬间不管表中的行的数目的。 这是因为在操作过程中不更新表中现有的行; 相反,默认值是只存储在表中的元数据,并根据需要访问这些行的查询值抬头。 此行为是自动的; 没有额外的语法需要实现超越ADD COLUMN语法的联机操作。 运行时不变的是,在表中在运行时会产生相同的值的每一行而不管其决定的表达。 例如,常量表达式“我的临时数据”,或系统函数GETUTCDATETIME()是运行时的常数。 与此相反,则各功能NEWID()或NEWSEQUENTIALID(),因为唯一的值产生对于表中的每个行不运行时的常数。 添加NOT NULL列与作为默认值不运行时恒定总是离线执行以及一个异(SCH-M)获取锁的操作的持续时间。

虽然现有的行引用存储在元数据中的值,默认值存储在一行被插入,不指定列另一个值的任何新行。 存储在元数据中的默认值被移动到当行被更新(即使在UPDATE语句中指定的实际列)的现有行中,或者如果表或聚簇索引重建。

类型为varchar(最大),为nvarchar(最大),VARBINARY(最大值),XML,文本,ntext的,图像,hierarchyid的,几何,地理 ,或CLR的UDT列,不能在网上操作进行添加。 A柱不能进行在线添加,如果这样做会导致最大可能的行大小超过8,060字节的限制。 列被添加作为在这种情况下的脱机操作。



Answer 5:

选择到一个新表,并重新命名。 例如,添加第i列到表A中:

select *, 1 as i
into A_tmp
from A_tbl

//Add any indexes here

exec sp_rename 'A_tbl', 'A_old'
exec sp_rename 'A_tmp', 'A_tbl'

要快而不会碰你的事务日志像分批可能插入。 (我这今天只是做瓦特/ <2分钟70万行的表)。

如果你需要它是一种在线操作(东西可能会在重命名选择的表成和改变),你可以用它在事务。



Answer 6:

另一种方法是将该列添加到一个新的相关表(假定一比一的关系,您可以通过给FK唯一索引强制执行)。 然后,您可以分批填充这一点,那么你可以添加一个连接到该表无论你想要的数据出现。 注意:我只会考虑这个对于我不希望在每个查询使用原始表,或者如果我原来的表的记录宽度变得太大,或者如果我加入一些列的列。



文章来源: How do I add a column to large sql server table