【问题标题】:Is there a better way to split work for simple updates?有没有更好的方法来拆分简单更新的工作?
【发布时间】:2019-07-05 09:49:11
【问题描述】:

我正在对一个非常简单的表中的一行进行 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';

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

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

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

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

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

【问题讨论】:

  • 大约有多少行会受到更新的影响?
  • @TabAlleman 百万。数以百万计。
  • @markb 检查我的答案更新

标签: sql sql-server optimization query-optimization sql-server-2014


【解决方案1】:

使用更新顶部

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

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

    if @@ROWCOUNT < 1000 BREAK
END

@@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

其他有用的链接

【讨论】:

  • 很好很简单,但它不允许 ORDER BY,至少根据文档是不允许的。你会认为它会,使用 TOP。
  • @TabAlleman 你是对的,你不能订购,在他们提到的文档中The rows referenced in the TOP expression used with INSERT, UPDATE, or DELETE are not arranged in any order.
  • @TabAlleman 但他们也提到了If you must use TOP to apply updates in a meaningful chronology, you must use TOP together with ORDER BY in a subselect statement. The following example updates the vacation hours of the 10 employees with the earliest hire dates.
  • 我明白了,但 tto 子选择不需要在其 WHERE 子句中使用 Column1 过滤器吗?
  • 最好将更新按索引列“分区”,以防止多次扫描表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-16
  • 1970-01-01
  • 2019-03-22
  • 2019-09-03
  • 1970-01-01
  • 2019-01-12
相关资源
最近更新 更多