更新非常简单;一个布尔字段需要设置为true / 1,我输入的是一个必须填充该字段的所有id的列表.(每行一个id)
当谈到这个大小的sql任务时,我并不是一个专家,所以我开始尝试1个UPDATE语句,其中包含“WHERE xxx IN({list of ids,以逗号分隔})”.首先,我尝试了一百万条记录.在测试服务器上的一个小数据集上,这就像一个魅力,但在生产环境中,这给出了一个错误.所以,我缩短了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条记录的神秘缺口?
>进行此更新的更好或最好的方法是什么? (因为我开始认为我正在做的事情可能非常低效和/或容易出错)
解决方法
create table TheIds (rownum int identity(1,1),id int); create view v_TheIds (select id from TheIds); bulk insert into v_TheIds . . .
利用数据库中的所有数据,您现在可以拥有更多选项.尝试更新:
update t set booleanfield = 1 where exists (select 1 from TheIds where TheIds.id = t.id)
您还应该在TheIds(id)上创建索引.
这是一个大型更新,全部作为一个事务执行.这可能会带来糟糕的性能影响并开始填充日志.您可以使用rownum列将其分解为较小的事务:
update t set booleanfield = 1 where exists (select 1 from TheIds where TheIds.id = t.id and TheIds.rownum < 1000)
这里的exists子句相当于左外连接.主要区别在于此相关子查询语法应该在其他数据库中起作用,其中与更新的连接是特定于数据库的.
使用rownum列,您可以根据需要为更新选择任意数量的行.因此,如果整体更新太大,您可以将更新置于循环中:
where rownum < 100000 where rownum between 100000 and 199999 where rownum between 200000 and 299999
等等.您不必这样做,但如果您因某些原因要批量更新,则可以.