将大表上的更改列速度提高到NON NULL


12

我最近在一个表中添加了一个可为NULL的位列,该表具有近5亿行。列上没有默认值,但是所有插入都将值指定为0或1,并且我运行了一次例程,将0或1分配给所有现有行(小批量更新行)。现在,每一行在该列中应具有0或1。

我想使bit列不可为空,但是当我尝试通过via进行操作时ALTER TABLE t1 ALTER COLUMN c1 bit not null,它开始运行了3分钟,并且我停止了它,因为它阻止了对表的所有读取,并且我怀疑它将花费很长时间才能完成。可能不会花费太长时间,但是我不能冒太多不可用的风险。回滚本身花费了6分钟。

您对我如何使该列不可为空而不可能花费数小时才能完成有什么建议? 另外,有什么方法可以估算ALTER TABLE ALTER COLUMN我开始然后取消的语句需要多长时间?

我正在使用SQL Server 2017 Web Edition。

Answers:


12

除了可以更改列定义之外,您还可以添加一个CHECK CONSTRAINT不允许该列为NULL的值。该表仍将需要进行扫描,但不需要修改每个数据页,因此它的操作速度要快得多。遗憾的是,在操作过程中仍将保留Sch-M锁。一种技巧是尝试在尝试添加约束之前将尽可能多的表放入缓冲池中。这样可以减少保持Sch-M锁的时间。

然后,您可以在下一个维护窗口期间删除约束并更改列定义。


谢谢乔的想法。我几乎添加了检查约束,但是在周末有一个维护时段,并且能够将列更改为不可为空。我不确定它是否有帮助,但是尝试将表数据放入缓冲池中,就在使列不可为空之前,我跑SELECT c1, count(*) FROM t1 GROUP BY c1了大约9分钟才能运行。之后的实际ALTER TABLE ALTER COLUMN陈述需要25分钟才能完成。还不错
Ben Amada

11

如果您使用的是Enterprise Edition(EE),则更好的策略可能是将其添加为NOT NULL默认值01(以最常见的为准)。

这是EE中仅元数据的更改。然后更新需要翻转的内容。这意味着更新较少,完成后无需更改列可为空性。- 马丁·史密斯


有趣的是,上周我在运行SQL开发人员版的本地计算机上测试将具有默认值的非空位列添加到同一张大表时注意到了此功能-该列立即添加,我不知道为什么。后来我才知道这一定是因为开发人员版包含EE功能。
Ben Amada

-3

尝试将数据复制到新表中,然后重命名。您必须注意所有约束和索引。这就是SSMS表设计器在想要对列进行重新排序时所做的事情(例如),但是您应该检查脚本以查看是否有任何看起来不正确的东西。

在复制过程中,对源表的读访问不是问题,但是如果有任何写操作,则可能会阻止或不复制它们,具体取决于隔离级别。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.