将值设置为超过500万行的表中的新日期时间列

时间:2015-02-05 15:01:24

标签: sql sql-server sql-server-2008-r2

我有一个名为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步的最有效方法是什么。所以这就是我想要的一些提示。

3 个答案:

答案 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步。