CIP*_*HER 9 sql sql-server alter-table sql-server-2008
我在一个实时数据库中有一个SQL表,它有超过600万行,我想提高特定列的精度:
ALTER TABLE sales ALTER COLUMN amount DECIMAL(8,4)
现在我的问题是,如果我执行上面的查询,SQL Server会重新计算每个单元格并将新值写回到同一个单元格中吗?(如果是,那意味着它肯定需要很长时间才能执行,而我们在数据库上的其他活动也会受到影响.)或者,该语句是否会以其他方式执行?
转换为decimal(8, 2)to decimal(8, 4)实际上并没有提高精度 ; 它正在增加规模.
因此,总的位数(因此,存储要求)没有改变.
如果你有超过9999.9999的任何值,你将会遇到算术溢出错误的错误时间.要容纳所有可能的(8,2)值,您需要增加列decimal(10, 4).
但是,这会增加列的存储要求,从5到9个字节.因此,这相当于update对可用性和事务日志的影响的声明.
我在测试中发现的是,至少对于SQL Server 2008R2,如果存储要求发生变化,增加的精度只会导致数据更新.基本上,如果列的新精度值与前一个相同的存储(或更小,并且没有发生截断)大小类别,则表数据不受影响.
对于600万行表,对事务日志的影响大约为2.5GB.它不一定会增长这个数量,但这将消耗多少空间.我的测试使用了大约200万行,该alter语句导致日志从1MB增长到~850MB.
至于对性能的影响(需要多长时间),不知道有关服务器硬件和负载的任何信息,这是不可能的.如果您非常担心要避免修改表,那么最好的方法可能是表交换:
sales_tmp使用所需的架构创建一个新表(),并复制数据:
insert sales_tmp
select * from sales;
如果可以确保sales在操作期间不会修改表,则不必担心使用事务和锁来阻止它.否则,repeatable read事务就足够了,并且至少sales在操作期间不会阻止对表的读取.
然后:
sales_tmp到sales)如果您在受影响的表上设置了复制或其他奇特的东西,这可能会有一些问题.遗憾的是,禁用和重新启用这些并非易事.
如果您担心更新600万条记录对事务日志的影响,则需要批量更新记录.其大小将根据您的需要而有所不同.我会推荐1,000-10,000.
IMO,我认为你真的不需要担心这个问题,除非你的数据库服务器真的受到空闲空间的限制,但这些信息可能对未来有用.
如果您的恢复模型是SIMPLE,那么日志包含也是如此.如果它是全的,事情就更难了.
尽管Blam在他的回答中声称,他的循环实现绝对不能保证任何包含事务日志文件.
checkpoint在循环体的末尾发出语句以确保刷新日志数据.SQL Server会定期执行此操作,在大多数情况下您不会注意到,但在某些情况下,您会注意到.下面是高度简化的psudeocode:
while @rows_left > 0
begin
    -- update/copy rows
    checkpoint;
end
这比较棘手,因为日志会无限增长,直到您进行日志备份,这会将日志页面标记为非活动状态,并使SQL Server能够重新使用已为日志文件分配的空间.除了推荐一些资源之外,我不会详细讨论这个问题: