我有一个名为Example的表,其行数超过5M。
我想知道创建一个不允许空值的新DateTime
列的最有效方法,并且默认值为Now。由于行数的原因,设置值会失败。
我想到的计划包括:
1)创建一个允许空值的新列。
ALTER TABLE Example
ADD RecordDate datetime
GO
2)一次将列的值设置为GETDATE()
1000(如果可能的话)或更多行。
3)一旦所有行都有值,我会改变列以不允许空值。
ALTER TABLE Example
ALTER COLUMN RecordDate datetime NOT NULL
我不确定完成第2步的最有效方法是什么。所以这就是我想要的一些提示。
答案 0 :(得分:2)
要通过具有顺序ID的大型表来处理批量应用更新,这种方法将起作用:
DECLARE @startID bigint
DECLARE @endID bigint
SELECT @startID=min(ID) from Example
WHILE @startID IS NOT NULL BEGIN
SELECT @endID=MAX(ID) FROM (
SELECT top(1000) ID from Example where ID>=@startID ORDER BY ID
) t
update Example
set RecordDate = GETDATE()
where ID between @startID and @endID AND RecordDate IS NULL
IF @@ROWCOUNT=0 BEGIN
SET @startID=NULL
END ELSE BEGIN
SET @startID=@endID
END
END
批量大小由
控制SELECT top(1000) ID from Example where ID>=@startID ORDER BY ID
根据需要调整1000以确保每个UPDATE快速完成。我已经使用这种技术每次更新批量更新了数亿行。
答案 1 :(得分:1)
我建议:
ALTER TABLE Example ADD COLUMN RecordDate datetime NOT NULL DEFAULT getdate();
无论你如何尝试,你都必须重写所有的数据记录,在每个页面上添加额外的字节值 - 即使值为NULL。
我认为以下内容可以最大限度地减少对数据的更改:
ALTER TABLE Example ADD _RecordDate datetime;
ALTER TABLE Example ADD FirstDateTime as (cast(<current datetime> as datetime));
ALTER TABLE Example ADD RecordDate as COALESCE(_RecordDate, FirstDateTime);
第二个想法,你仍然需要保留页面上_RecordDate
的空间,所以第一种方法可能是最好的。
另一种方法是设置另一个具有相同主键和记录日期的表。这需要left join
来获取信息,但只有在您访问该列时才需要这样做。
答案 2 :(得分:0)
mmilan
您可以在第1步尝试此脚本:
ALTER TABLE Example ADD RecordDate DATETIME NOT NULL DEFAULT GETDATE()
现在你不需要第2步和第3步。