在一个更新查询中更新100k记录

时间:2012-09-07 07:44:37

标签: sql sql-server stored-procedures sql-update

是否可以或建议运行一个更新查询,一次更新近100k条记录?

如果是这样,我该怎么做?我试图将一个数组传递给我的存储过程,但它似乎不起作用,这是我的SP:

CREATE PROCEDURE [dbo].[UpdateAllClients]
    @ClientIDs varchar(max)
AS
BEGIN
    DECLARE @vSQL varchar(max)
    SET @vSQL = 'UPDATE Clients SET LastUpdate=GETDATE() WHERE ID IN (' + @ClientIDs + ')';
    EXEC(@vSQL);
END

我不知道什么不起作用,但它只是没有更新相关的查询。

任何?

7 个答案:

答案 0 :(得分:5)

UPDATE整体上正在读取您的@ClientIDs作为逗号分隔值)。为了说明这一点,你就是这样做的。

假设@ClientIDs = 1,2,3,4,5

你的UPDATE命令正在解释它

UPDATE Clients SET LastUpdate=GETDATE() WHERE ID IN ('1,2,3,4,5')';

而不是

UPDATE Clients SET LastUpdate=GETDATE() WHERE ID IN (1,2,3,4,5)';

您的问题的一个建议是在UPDATE上使用子查询,示例

UPDATE Clients 
   SET LastUpdate = GETDATE() 
WHERE ID IN
    (
       SELECT ID
       FROM tableName
       -- where condtion
    )

希望这是有道理的。

hope this helps

答案 1 :(得分:3)

需要注意的一些注意事项。

像这样的大更新可以锁定目标表。如果> 5000行受操作影响,单个行锁将被提升为表锁,这将阻止其他进程。值得注意的是,如果这可能会导致您的方案出现问题。请参阅:Lock Escalation

要像这样更新大量行,我要考虑的方法是(基本的):

  1. 将100K Ids批量插入临时表(例如,从.NET,使用SqlBulkCopy)
  2. 使用连接到上面的临时表
  3. 更新目标表
  4. 删除临时表
  5. 这为控制流程提供了更多空间,但是将工作负载分成多个块并一次x行。

答案 2 :(得分:0)

如果您提供数组,则传递给“IN”的项目数量有限制。

因此,如果您只想更新整个表格,请跳过IN条件。

如果没有在IN中指定SQL。那应该做的工作

答案 3 :(得分:0)

数据库很可能会拒绝该SQL语句,因为它太长了。

当您需要一次更新这么多记录时,那么您的数据库架构可能不合适。也许LastUpdate数据不应该为每个客户端单独存储,而是全局只存储一次,或者对于一组常量客户端只能存储一次?

但如果不了解整体情况,很难推荐一个好的行动方案。

答案 4 :(得分:0)

您使用的是哪个版本的sql server?如果是2005年以上,我建议使用TVP(表值参数 - http://msdn.microsoft.com/en-us/library/bb510489.aspx)。数据传输速度更快(而不是构建一个巨大的字符串),您的查询看起来会更好:

update c
set lastupdate=getdate()
from clients c
join @mytvp t on c.Id = t.Id

答案 5 :(得分:0)

每个SQL语句本身都是transaction语句。这意味着sql server将为所有这些百万行获取锁。它实际上可以降低表的性能。所以你真的不倾向于更新一个有数百万行的表,这会损害性能。所以解决方法是在DML操作之前设置rowcount

set rowcount=100
UPDATE Clients SET LastUpdate=GETDATE()
WHERE ID IN ('1,2,3,4,5')';
set rowcount=0

或从SQL Server 2008,您可以参数化Top关键字

Declare @value int
set @value=100000 
again:
UPDATE top (@value) Clients SET LastUpdate=GETDATE()
WHERE ID IN ('1,2,3,4,5')';
if @@rowcount!=0  goto again 

查看上述查询的速度有多快,然后调整并更改变量的值。您需要按照上述答案的建议打破较小单位的任务

答案 6 :(得分:0)

方法1:

  1. 将@clientids拆分为分隔符','
  2. 放入数组并遍历该数组
  3. 为每个ID更新客户表。
  4. OR

    方法2:

    不要将@clientids作为varchar2,请按照以下步骤进行操作

    1. 为ids创建对象类型表并使用join。
    2. 为了加快处理速度,你也可以在clientid上创建索引。