我想从有大约 400 万条记录的表中更改一个字段。我确保所有这些字段值都不是 NULL 并且想要将此字段更改为 NOT NULL
ALTER TABLE dbo.MyTable
ALTER COLUMN myColumn int NOT NULL
...似乎永远需要做这个更新。有什么方法可以加快速度,还是我只是在下班时间过夜?
这也可能导致表锁吗?
我想从有大约 400 万条记录的表中更改一个字段。我确保所有这些字段值都不是 NULL 并且想要将此字段更改为 NOT NULL
ALTER TABLE dbo.MyTable
ALTER COLUMN myColumn int NOT NULL
...似乎永远需要做这个更新。有什么方法可以加快速度,还是我只是在下班时间过夜?
这也可能导致表锁吗?
您可以在不检查字段的情况下更改字段并使其不为空。如果您真的担心不在下班时间这样做,您可以向该字段添加一个约束,以确保它不为空。这将允许您使用 with no check 选项,而不是让它检查 400 万行中的每一行以查看它是否更新。
CREATE TABLE Test
(
T0 INT Not NULL,
T1 INT NUll
)
INSERT INTO Test VALUES(1, NULL) -- Works!
ALTER TABLE Test
WITH NOCHECK
ADD CONSTRAINT N_null_test CHECK (T1 IS NOT NULL)
ALTER COLUMN T1 int NOT NULL
INSERT INTO Test VALUES(1, NULL) -- Doesn't work now!
真的你有两个选择(添加第三个见编辑):
根据您的具体情况,任何一个选项都可能更适合您。我不会选择该选项,因为您必须在下班时间运行它。从长远来看,与通过走捷径节省几个小时可能面临的头痛相比,您在半夜进行更新所花费的时间将得到很好的利用。
综上所述,如果您要使用选项二,您可以最大限度地减少您在非工作时间所做的工作量。由于您必须确保在更改列之前将行更新为不为空,因此您可以将游标写入缓慢(相对于一次完成所有操作)
编辑: 我只是想到了第三种选择:你可以创建一个新表,里面有适当的列,然后将数据从原表导出到新表。完成后,您可以删除原始表并将新表的名称更改为旧表。为此,您必须禁用对原始文件的依赖项,并在完成后将它们重新设置为新的依赖项,但此过程将大大减少您在下班时间必须做的工作量。当您通过管理工作室对表进行列排序更改时,这与 sql server 使用的方法相同。对于这种方法,我会分块进行插入,以确保您不会对系统造成撤消压力并阻止其他人访问它。然后在下班时间,你可以放弃原来的,重命名第二个,
链接到使用sp_rename。
我所知道的“快速”(*)执行此操作的唯一方法是
您可能希望在事务之外执行最后一步,因为这可能需要相当长的时间,具体取决于引用此表的表的数量和大小,第一步根本不会花费太多时间
与往常一样,最好先在测试服务器上进行测试运行 =)
PS:请不要试图用 NOCHECK 重新创建 FK,这会使它们变得徒劳,因为优化器在构建查询计划时不会信任它们也不会考虑它们。
(*:很快归结为:停机时间最短)
很抱歉让您灰心,但是:
与您没有直接关系(因为它是关于从 NOT NULL 到 NULL),但是关于这个主题的有趣阅读:http: //beyondrelational.com/blogs/sankarreddy/archive/2011/04/05/is-alter-table- alter-column-not-null-to-null-always-expensive.aspx
最后是一些古老的历史——关于 2005 年论坛中的一个等效问题,与上面提供的@Kevin 提出了相同的建议——使用约束而不是使列本身不可为空:http ://www.sqlteam.com/Forums /topic.asp?TOPIC_ID=50671