如何加快数百万行的简单UPDATE查询?

时间:2016-01-19 00:49:55

标签: sql sql-server tsql sql-server-2012

如何加快这个相当简单的UPDATE查询?它已经运行了5个多小时!

我基本上通过加入一个包含旧ID和新ID的新表来替换表中的SourceID。所有这些字段都是VARCHAR(72)并且必须保持这种状态。

Pub_ArticleFaculty表有8,354,474行(830万)。 ArticleAuthorOldNew有99,326,472行(9930万),只有你在下面看到的2个字段。

所有这些字段都有单独的非聚集索引。是否有更好的方法来编写此查询以使其运行得更快?

UPDATE PF
        SET PF.SourceId = AAON.NewSourceId
    FROM AA..Pub_ArticleFaculty PF WITH (NOLOCK)
        INNER JOIN AA2..ArticleAuthorOldNew AAON WITH (NOLOCK)  
                   ON AAON.OldFullSourceId = PF.SourceId

4 个答案:

答案 0 :(得分:2)

如果您要重置所有或几乎所有值,那么List将非常昂贵。这是由于日志记录和更新的开销。

您可以采用的一种方法是将update放入临时表中,然后截断,然后重新插入:

insert

注意:您应该确保原始表中的列与临时表匹配,或者更好的是,在select pf.col1, pf.col2, . . . , coalesce(aaon.NewSourceId, pf.sourceid) as SourceId into temp_pf from AA..Pub_ArticleFaculty PF LEFT JOIN AA2..ArticleAuthorOldNew AAON on AAON.OldFullSourceId = PF.SourceId; truncate table AA..Pub_ArticleFaculty; insert into AA..Pub_ArticleFaculty select * from temp_pf; 中明确列出列。

我还应该注意,主要的好处是恢复模式简单或批量记录。原因是截断日期insertselect into的日志记录很少(请参阅here)。节省日志记录可能非常重要。

答案 1 :(得分:2)

根据我的经验,循环更新以使其在每次迭代时对少量行进行操作是一种很好的方法。更新每次迭代的理想行数在很大程度上取决于您的环境和您正在使用的表。我通常每次迭代大约1,000 - 10,000行。

示例

SET ROWCOUNT 1000 -- Set the batch size (number of rows to affect each time through the loop).
WHILE (1=1) BEGIN

    UPDATE PF
    SET NewSourceId = 1
    FROM AA..Pub_ArticleFaculty PF WITH (NOLOCK)
            INNER JOIN AA2..ArticleAuthorOldNew AAON WITH (NOLOCK)  
                       ON AAON.OldFullSourceId = PF.SourceId
    WHERE NewSourceId IS NULL -- Only update rows that haven't yet been updated.

    -- When no rows are affected, we're done!
    IF @@ROWCOUNT = 0
        BREAK
END
SET ROWCOUNT 0 -- Reset the batch size to the default (i.e. all rows).
GO

答案 2 :(得分:1)

我会

  • 禁用PF.SourceId上的索引
  • 运行更新
  • 然后重建索引

我没有在你正在更新的表上获得NOLOCK

UPDATE PF
SET PF.SourceId = AAON.NewSourceId
FROM AA..Pub_ArticleFaculty PF 
INNER JOIN AA2..ArticleAuthorOldNew AAON WITH (NOLOCK)  
        ON AAON.OldFullSourceId = PF.SourceId 
       AND PF.SourceId <> AAON.NewSourceId

答案 3 :(得分:0)

我没有足够的意见来评论这个问题。所以我将其添加为答案。你能检查基本的

吗?
  1. 桌子上的任何触发器?如果是这样,你的更新行就会达到那么多次。如果有这样的链,那将是性能下降的原因。

  2. 加入列上是否有索引?

  3. 在其他情况下,系统表现良好吗?验证系统有足够的电量

  4. 但如果处理得当,800万条记录的运行时间超过1分钟并不多。 5小时意味着其他问题