RNo*_*bel 6 sql t-sql sql-server data-migration sql-server-2008
在迁移项目期间,我面临着SQL Server中400万条记录的更新.
更新非常简单; 一个布尔字段需要设置为true/1,我输入的是一个必须填充该字段的所有id的列表.(每行一个id)
当谈到这个大小的sql任务时,我不是一个专家,所以我开始尝试包含" WHERE xxx IN ( {list of ids, separated by comma} )"的1 UPDATE语句.首先,我尝试了一百万条记录.在测试服务器上的一个小数据集上,这就像一个魅力,但在生产环境中,这给出了一个错误.所以,我缩短了ID列表的长度几次,但无济于事.
我尝试的下一件事是将列表中的每个id转换为UPDATE语句(" UPDATE yyy SET booleanfield = 1 WHERE id = '{id}'").某处,我读到每隔x行有一个GO是好的,所以我每100行插入一次GO(使用优秀的'sed'工具,从unix移植).
因此,我将400万个更新语句的列表分成每个250.000的部分,将它们保存为sql文件,并开始加载并运行第一个到SQL Server Management Studio(2008).请注意我也尝试过SQLCMD.exe,但令我惊讶的是,这比SQL Studio慢了大约10-20倍.
完成大约需要1.5小时,导致"查询已完成并出现错误".但是,messages-list包含一个很好的列表"受影响的1行"和"0行受影响",后者用于未找到id时.
接下来,我使用COUNT(*)检查了表中更新记录的数量,发现更新语句数量与更新记录数量之间存在数千条记录的差异.
然后我认为这可能是由于不存在的记录,但当我减去输出中"0行受影响"的数量时,有895条记录的神秘缺口.
我的问题:
有没有办法找出"查询已完成但有错误"中的错误描述和原因.
如何解释895记录的神秘差距?
有什么更好或最好的方法来进行此更新?(因为我开始认为我正在做的事情可能非常低效和/或容易出错)
解决此问题的最佳方法是将400万条记录插入表格中.实际上,您可以将它们放入带有标识列的表中,通过"批量插入"到视图中.
create table TheIds (rownum int identity(1,1), id int);
create view v_TheIds (select id from TheIds);
bulk insert into v_TheIds . . .
Run Code Online (Sandbox Code Playgroud)
利用数据库中的所有数据,您现在可以拥有更多选项.尝试更新:
update t
set booleanfield = 1
where exists (select 1 from TheIds where TheIds.id = t.id)
Run Code Online (Sandbox Code Playgroud)
您还应该创建一个索引TheIds(id).
这是一个大型更新,全部作为一个事务执行.这可能会带来糟糕的性能影响并开始填充日志.您可以使用该rownum列将其分解为较小的事务:
update t
set booleanfield = 1
where exists (select 1 from TheIds where TheIds.id = t.id and TheIds.rownum < 1000)
Run Code Online (Sandbox Code Playgroud)
这里的exists子句就是相当于left outer join.主要区别在于此相关子查询语法应该在其他数据库中起作用,其中与更新的连接是特定于数据库的.
使用该rownum列,您可以根据需要为更新选择任意数量的行.因此,如果整体更新太大,您可以将更新置于循环中:
where rownum < 100000
where rownum between 100000 and 199999
where rownum between 200000 and 299999
Run Code Online (Sandbox Code Playgroud)
等等.您不必这样做,但如果您因某些原因要批量更新,则可以.
关键的想法是将id列表放入数据库中的表中,这样您就可以使用数据库的强大功能进行后续操作.
| 归档时间: |
|
| 查看次数: |
4786 次 |
| 最近记录: |