Adi*_*dit 9 sql t-sql sql-server sql-server-2005 large-data-volumes
数据库:SQL Server 2005
问题:将值从一列复制到同一个表中的另一列,其中包含十亿+行.
test_table (int id, bigint bigid)
Run Code Online (Sandbox Code Playgroud)
事情尝试1:更新查询
update test_table set bigid = id
Run Code Online (Sandbox Code Playgroud)
填充事务日志并由于缺少事务日志空间而回滚.
尝试2 - 以下行的程序
set nocount on
set rowcount = 500000
while @rowcount > 0
begin
update test_table set bigid = id where bigid is null
set @rowcount = @@rowcount
set @rowupdated = @rowsupdated + @rowcount
end
print @rowsupdated
Run Code Online (Sandbox Code Playgroud)
上述过程随着进行而开始减慢.
尝试3 - 创建游标以进行更新.
通常不鼓励SQL Server文档,这种方法一次更新一行,这太耗时了.
是否有一种方法可以加速将值从一列复制到另一列.基本上我正在寻找一些"魔术"关键字或逻辑,它将允许更新查询按顺序一次撕掉50亿行.
任何提示,指针将非常感激.
在UPDATE语句中使用TOP :
UPDATE TOP (@row_limit) dbo.test_table
SET bigid = id
WHERE bigid IS NULL
Run Code Online (Sandbox Code Playgroud)
我猜想您即将达到21亿个列的人工键上INT数据类型的限制。是的,那很痛苦。比实际达到该限制之前要容易得多,而在尝试解决此问题时,生产就会关闭:)
无论如何,这里的一些想法是可行的。不过,让我们谈谈速度,效率,索引和日志大小。
该日志最初被炸毁是因为它试图一次提交所有2b行。其他帖子中有关“分块”的建议将起作用,但是可能无法完全解决日志问题。
如果数据库处于“简单”模式,您会没事的(每次批处理后日志将重新使用)。如果数据库处于FULL或BULK_LOGGED恢复模式,则必须在运行操作期间频繁运行日志备份,以便SQL可以重新使用日志空间。这可能意味着在此期间增加备份频率,或者仅在运行时监视日志使用情况。
where bigid is null随着表的填充,所有答案都会放慢速度,因为(大概)新的BIGID字段上没有索引。您可以(当然)仅在BIGID上添加索引,但是我不认为这是正确的答案。
键(双关语意味)是我的假设,即原始ID字段可能是主键或聚集索引,或两者兼有。在这种情况下,让我们利用这一事实,对Jess的想法进行一些修改:
set @counter = 1
while @counter < 2000000000 --or whatever
begin
update test_table set bigid = id
where id between @counter and (@counter + 499999) --BETWEEN is inclusive
set @counter = @counter + 500000
end
Run Code Online (Sandbox Code Playgroud)
由于ID上已有索引,因此这应该非常快。
无论如何,实际上没有必要进行ISNULL检查,间隔上的我(-1)也不是。如果我们在两次调用之间重复一些行,那没什么大不了的。
| 归档时间: |
|
| 查看次数: |
4659 次 |
| 最近记录: |