Bob*_*bst 44 sql sql-server sql-server-2005
我需要在一个1.2亿记录表中初始化一个值为-1的新字段.
Update table
set int_field = -1;
Run Code Online (Sandbox Code Playgroud)
我让它运行了5个小时才取消它.
我尝试运行它,事务级别设置为读取未提交的相同结果.
Recovery Model = Simple.
MS SQL Server 2005
Run Code Online (Sandbox Code Playgroud)
如何更快地完成这项工作?
Pet*_*hia 36
更新120M记录表的唯一合理方法是使用SELECT填充第二个表的语句.这样做时你必须小心.说明如下.
简单案例
对于没有聚集索引的表,在w/out并发DML的时间内:
SELECT *, new_col = 1 INTO clone.BaseTable FROM dbo.BaseTable如果无法创建克隆架构,则同一架构中的其他表名称将起作用.切记在切换后重命名所有约束和触发器(如果适用).
非简单案例
首先,BaseTable在不同的模式下重新创建相同的名称,例如clone.BaseTable.使用单独的模式将在以后简化重命名过程.
然后,测试你的插件w/1000行:
-- assuming an IDENTITY column in BaseTable
SET IDENTITY_INSERT clone.BaseTable ON
GO
INSERT clone.BaseTable WITH (TABLOCK) (Col1, Col2, Col3)
SELECT TOP 1000 Col1, Col2, Col3 = -1
FROM dbo.BaseTable
GO
SET IDENTITY_INSERT clone.BaseTable OFF
Run Code Online (Sandbox Code Playgroud)
检查结果.如果一切按顺序出现:
这需要一段时间,但不会像更新那么长.完成后,检查克隆表中的数据以确保一切正确.
然后,重新创建所有非群集主键/唯一约束/索引和外键约束(按此顺序).如果适用,重新创建默认值并检查约束.重新创建所有触发器.在单独的批处理中重新创建每个约束,索引或触发器.例如:
ALTER TABLE clone.BaseTable ADD CONSTRAINT UQ_BaseTable UNIQUE (Col2)
GO
-- next constraint/index/trigger definition here
Run Code Online (Sandbox Code Playgroud)
最后,转到dbo.BaseTable备份架构和clone.BaseTabledbo架构(或者您的表应该存在的任何位置).
-- -- perform first true-up operation here, if necessary
-- EXEC clone.BaseTable_TrueUp
-- GO
-- -- create a backup schema, if necessary
-- CREATE SCHEMA backup_20100914
-- GO
BEGIN TRY
BEGIN TRANSACTION
ALTER SCHEMA backup_20100914 TRANSFER dbo.BaseTable
-- -- perform second true-up operation here, if necessary
-- EXEC clone.BaseTable_TrueUp
ALTER SCHEMA dbo TRANSFER clone.BaseTable
COMMIT TRANSACTION
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() -- add more info here if necessary
ROLLBACK TRANSACTION
END CATCH
GO
Run Code Online (Sandbox Code Playgroud)
如果您需要释放磁盘空间,此时可能会删除原始表,但保持一段时间可能是谨慎的.
不用说,这理想情况下是离线操作.如果您在执行此操作时有人修改数据,则必须使用架构开关执行校正操作.我建议创建一个触发器,dbo.BaseTable将所有DML记录到一个单独的表中.在开始插入之前启用此触发器.然后,在执行模式传输的同一事务中,使用日志表执行校正.首先在数据子集上进行测试!Deltas很容易搞砸.
小智 13
如果您有磁盘空间,则可以使用SELECT INTO并创建新表.它的记录最少,因此速度会快得多
select t.*, int_field = CAST(-1 as int)
into mytable_new
from mytable t
-- create your indexes and constraints
GO
exec sp_rename mytable, mytable_old
exec sp_rename mytable_new, mytable
drop table mytable_old
Run Code Online (Sandbox Code Playgroud)
小智 9
我将任务分解为更小的单位.为您的表测试不同的批处理大小间隔,直到找到最佳执行的间隔.这是我过去使用过的一个示例.
declare @counter int
declare @numOfRecords int
declare @batchsize int
set @numOfRecords = (SELECT COUNT(*) AS NumberOfRecords FROM <TABLE> with(nolock))
set @counter = 0
set @batchsize = 2500
set rowcount @batchsize
while @counter < (@numOfRecords/@batchsize) +1
begin
set @counter = @counter + 1
Update table set int_field = -1 where int_field <> -1;
end
set rowcount 0
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
115748 次 |
| 最近记录: |