有没有更好的方法来分割简单更新的工作?

mar*_*k b 3 sql sql-server optimization query-optimization sql-server-2014

我正在对表中的一行进行 MS SQL Server 更新,这非常简单。我正在用另外 4 件东西替换大约 4 件东西。

update Table set Column1 = 'something new' where Column1 = 'something old';
update Table set Column1 = 'something new 2' where Column1 = 'something old 2';
update Table set Column1 = 'something new 3' where Column1 = 'something old 3';
update Table set Column1 = 'something new 4' where Column1 = 'something old 4';
Run Code Online (Sandbox Code Playgroud)

这就是全部内容了。但我的问题是,这是一个在生产中运行的包含大量记录的表,但在运行更新之前确切的数量是未知的。有一个时间戳列。首先更新最新的可能更重要。

但我的问题可能是一个更实际的问题。

最好按时间戳对其进行分区并让它手动运行,还是有更好的方法让它运行?我还可以按每个更新语句来划分工作。

或者有什么方法可以将这样的东西放入脚本本身吗?

我尝试查看查询计划,但它没有告诉我拆分查询的最佳方法。

Had*_*adi 5

使用更新顶部

您可以使用 while 循环和 Update Top 选项将数据更新为块:

WHILE 1 = 1
BEGIN
    UPDATE top (1000) tableToUpdate
    SET Column1 = 'something new'
    WHERE 
       Column1 = 'something old';

    if @@ROWCOUNT < 1000 BREAK
END
Run Code Online (Sandbox Code Playgroud)

@@ROWCOUNT小于1000块大小时,意味着所有行都被更新。

请注意,根据官方文档:

用于 INSERT、UPDATE 或 DELETE 的 TOP 表达式中引用的行不按任何顺序排列。

使用 TOP 和 Order BY 更新

如果您希望根据时间戳更新排序数据,在官方文档中他们提到:

如果必须使用 TOP 按有意义的时间顺序应用更新,则必须在子选择语句中将 TOP 与 ORDER BY 一起使用。

例如:

WHILE 1 = 1
BEGIN
    UPDATE tableToUpdate
    SET Column1 = 'something new'
    FROM (SELECT TOP 1000 IDColumn FROM tableToUpdate WHERE tableToUpdate.Column1 = 'something old' ORDER BY TimeStamp DESC) tto
    WHERE 
       tableToUpdate.ID = tto.ID;

    if @@ROWCOUNT < 1000 BREAK
END
Run Code Online (Sandbox Code Playgroud)

其他有用的链接

  • 最好通过索引列对更新进行“分区”,以防止多次扫描表。 (2认同)