【问题标题】:simple UPDATE query on large table has bad performance大表上的简单 UPDATE 查询性能不佳
【发布时间】:2019-02-27 07:25:53
【问题描述】:

我需要通过一个存储过程做如下更新查询:

UPDATE table1
SET name = @name (this is the stored procedure inputparameter)
WHERE name IS NULL

Table1 没有索引或键,5 列是 4 个整数和 1 个 varchar(可更新列 'name' 是 varchar 列)

NULL 记录大约有 15.000.000 行需要更新。这需要大约 50 分钟,我认为这太长了。

我正在运行 Azure SQL DB Standard S6(400DTU)。

谁能给我一个提高性能的建议?

【问题讨论】:

  • 您是否希望将所有空名称值更新为特定值或更新任何特定 ID?
  • 所有NULL值都必须更新为@name,大约1500万条记录,没有特定ID
  • 您没有提到您是否真的可以选择创建索引或扩展 SQL Server(即到 P 级别)。这是提高性能的两个步骤
  • 如果我做对了,你每秒更新 5000 行。是什么让这太慢了?

标签: sql sql-server stored-procedures azure-sql-database


【解决方案1】:

由于您没有任何键或索引,我可以建议以下方法。

1- 使用INTO(将复制数据)创建一个新表,如下查询。

  SELECT 
       CASE 
              WHEN NAME IS NULL THEN @name 
              ELSE NAME 
       END AS NAME, 
       <other columns > 
INTO   dbo.newtable
FROM table1

2- 删除旧表

drop table table1

3- 将新表重命名为table1

exec sp_rename 'dbo.newtable', 'table1'

另一种方法是使用批量更新,有时您可以获得比批量更新更好的性能(您需要通过调整批量大小进行测试)。

WHILE EXISTS (SELECT 1 FROM table1 WHERE name is null)
BEGIN
    UPDATE TOP (10000) table1
    SET name = @name
    WHERE n ame is null
END

【讨论】:

    【解决方案2】:

    你可以用下面的方法吗?

    UPDATE table1
    SET name = ISNULL(name,@name)
    

    对于 null 值,它将使用 @name 更新,其余的将使用相同的值更新。

    【讨论】:

      【解决方案3】:

      没有。您正在更新 15,000,000 行,这将需要很长时间。每次更新都会产生查找行和记录值的开销。

      有这么多行要更新,开销不太可能是查找行。如果您在name 上添加索引,则更新实际上必须更新索引以及更新原始值。

      如果您关心的是锁定数据库,您可以设置一个循环,在其中反复执行类似的操作:

      UPDATE TOP (100000) table1
          SET name = @name (this is the stored procedure inputparameter)
          WHERE name IS NULL;
      

      100,000 行大约需要 30 秒左右。

      在这种情况下,name 上的索引确实有帮助。否则,循环的每次迭代本质上都会读取整个表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-12
        • 1970-01-01
        • 2016-06-21
        • 2019-07-31
        • 2011-11-20
        • 1970-01-01
        相关资源
        最近更新 更多