2016-06-21 81 views
2

我们有一个SQL Server 2008数据库,其中包含超过14亿条记录的表。由于坐标系调整,我们必须将坐标列的数据类型从decimal(18, 2)扩展到decimal(18, 3)更改SQL Server中列的数据类型

我们已经尝试了多件事情,但在执行约14小时后,所有事情都会导致异常(事务日志已满)。

这是我们尝试的事情:

  1. ALTER TABLE

    ALTER TABLE Adress 
    ALTER COLUMN Coordinate decimal(18, 3) NULL 
    
  2. 设计师

    • 取消选中Tools > Options > Designer > Prevent saving changes that require table re-creation
    • 打开的设计
    • 更改数据类型为decimal(18, 3)
    • Right-click > Generate Change Script...

这是什么脚本,是创建一个新表的新数据类型,旧的数据复制到新表,删除旧表并重命名新表。

不幸的是,两次尝试都会在执行14小时后导致事务日志完全异常。

我认为,通过ALTER TABLE... ALTER COLUMN...改变数据类型只是改变元数据,应该在(毫秒)秒内完成?

  • 你知道我可以尝试的其他方法吗?
  • 为什么我的尝试(特别是#1)需要那么多时间?

在此先感谢

+2

** **的一些变化到表可以执行,因为元数据只是变化。绝不是*全部*变化,并且您正在执行的操作确实需要更新每一行。所以,我想你需要更多的日志空间。 –

+0

尝试''选择CONVERT(二进制(8),CONVERT(十进制(18,3),1.5)),CONVERT(二进制(8),CONVERT(十进制(18,2),1.5))'',你会看到*代表*是完全不同的。 –

+0

A.表使用的空间有多大(磁盘使用情况报告)? B.您的实验有多少磁盘空间?如果B> A,那么可以考虑从头开始创建新表并将数据分发给它(这可以分批完成,从而最大限度地减少事务日志的使用)。作为副作用的好处,您将获得更紧凑和更少碎片化的数据组织。如果还未使用,还应该使用压缩 – Jan

回答

3

好,主要问题似乎大量保存到表中的数据。你们俩的尝试似乎也很好。由于数据量很大,他们都必须花时间。

每当您更改列数据类型时,SQL SERVER会尝试将现有数据转换为目标数据类型。处理大量数据的转换可能会导致执行延迟。

此外,我不知道你是否有任何触发在桌子上。

好吧!最后,我会建议你遵循以下步骤。尝试至少

  1. 删除指向旧列的所有主键/索引/约束,并禁用任何触发器(如果有)。
  2. 引入一个新的可为空的列与新的数据类型(即使 它意味着非空)的表。
  3. 现在对表进行更新查询,将新列值设置为旧列值。您可以在更新1000/100000批记录的同时进行块更新。并且您还可以将条件应用于查询以获得更好的结果。
  4. 一旦通过将新列值设置为旧列来更新所有表格,然后从设计器(如果它的意思是NOT NULL)删除NULL字符到NOT NULL
  5. 删除/删除旧列。执行选择查询并验证您的更改。

最后一点我应该添加的是你的数据库事务日志也满了,可以缩小但有一些预防措施。 Here是非常好的示例,如何重置您的事务日志。也应该看看这个。

希望这有助于。 :)

1

解决方法是批量更新,缓解日志文件的压力。

方法1:
a)用新定义创建一个新表。 b)将数据批量复制到新表中。
c)丢弃旧桌子。
d)重新命名新表格。

方法2:
a)创建一个正确定义的新列。
b)分批更新旧栏中的数据。
c)丢弃旧列。
d)重新命名新列。

方法3:
a)将数据转换为文件。
b)截断表格。
c)改变色谱柱。
d)将恢复模型设置为批量记录或简单。 e)将文件中的数据转换为表格。 f)将恢复模型设置回完整。

1

这是我的建议: 添加一个字段到表并将其命名为象下面这样:

NewCoordinate DECIMAL(18,3)NULL

WHILE(1 = 1) 
BEGIN 
    UPDATE TOP(1000) Adress SET NewCoordinate = Coordinate 
    WHERE NewCoordinate IS NULL 
     IF (@@ROWCOUNT < 1000)  
    BREAK  
END 

尽量保持你的交易之类的小。

并最终放弃您的坐标字段。

+0

其中NewCoordinate <>坐标 – Paparazzi

0

添加新列作为最后一列
如果试图在最后一栏前插入它可能需要很长的时间
NewCoordinate十进制(18,3)NULL

select 1 
while(@@rowcount > 0) 
BEGIN 
    UPDATE TOP(10000) Adress 
    SET NewCoordinate = Coordinate 
    WHERE NewCoordinate <> Coordinate 
END