【问题标题】:SQL Server - Most efficient way to do multiple updates when WHERE cause is a unique IDSQL Server - 当 WHERE 原因是唯一 ID 时进行多次更新的最有效方法
【发布时间】:2020-04-06 15:16:20
【问题描述】:

假设我在 SQL Server 数据中有 10-20k 条记录要更新,我需要执行以下操作:-

UPDATE dbo.MyTable SET Field1 = 95 WHERE MyTableID = 348923
UPDATE dbo.MyTable SET Field1 = 90 WHERE MyTableID = 348924
UPDATE dbo.MyTable SET Field1 = 100 WHERE MyTableID = 348925

MyTableID 是主键,因此保证每次都不同。我想知道运行这个最有效的方法是什么,当你开始连续使用 10k 到 20k 甚至更多的 UPDATE 语句时,因为我已经读过每个 UPDATE 都是对该表的查找,这已经很大了。

我考虑过并且知道:-

  • 光标(目前看起来更可取)
  • 如上所述的单一更新列表,只需处理缓慢

谁能建议最有效的方法是什么?

谢谢。

【问题讨论】:

    标签: sql sql-server database sql-update sqlperformance


    【解决方案1】:

    运行多个查询可能是一种有效的方法,因为它可以利用主键索引。

    您也可以尝试使用条件表达式,例如:

    UPDATE dbo.MyTable 
    SET Field1 = case MyTableID
        WHEN 348923 HEN 95
        WHEN 348924 THEN 90
        WHEN 348924 THEN 100
    END
    WHERE MyTableID IN (348923, 348924, 348925)
    

    如果要更新的 id 列表确实在范围内,WHERE 子句可以按以下形式优化,这将利用索引:

    WHERE MyTableID BETWEEN 348923 AND 348925
    

    【讨论】:

      【解决方案2】:

      在 SQL Server 中,我推荐JOIN

      UPDATE t
          SET Field1 = v.Field1
          FROM dbo.MyTable t JOIN
               (VALUES (95, 348923),
                       (90, 348924),
                       (100, 348925)
               ) v(Field1, MyTableId)
               ON v.MyTableId = t.MyTableId;
      

      这应该与使用CASE 具有基本相同的性能。我觉得更容易管理。如果你想设置多列,那就更简单了。

      【讨论】:

        【解决方案3】:

        准备一个脚本模板,通过创建如下表变量来处理更新

        declare @your_tbl_name table
        {
        MyTableID int,
        Field1 int
        }
        

        将所有值插入此表变量

        insert into @your_tbl_name
        select Field1,MyTableID from your [actualsource]
        

        将此表变量与实际表进行内连接并更新值。

        update t 
        set t.Field1 = tbl.Field1
        from dbo.MyTable t 
        inner join @your_tbl_name tbl
        on t.MyTableID = tbl.MyTableID
        

        【讨论】:

          【解决方案4】:

          我认为 Gordon Linoff 提供了一个很好的方法。 要确定这是否可行,您需要即时更新还是可以批量更新?

          如果您可以批量处理它们,请考虑更新需要多久反映一次主表。 您可能会更幸运地将所有更改添加到临时表中,然后再运行更新。这实际上取决于您需要的性能,以及您今天的性能。如果您有一堆个人用户同时运行更新,并且每个用户都需要能够立即更新单独的数据,那么需要考虑不同的方法。但是,如果您只能经常处理这些值的更新,请批量处理它们!我从向我公司出售产品的公司那里收到了大量更新,这是我必须采取的提高效率的途径。

          如果您可以使用暂存表,这就是该批次的外观。

          --Creates a staging table
          create table dbo.StageUpdates
              (
              ID int primary key
              , NewValue int
              )
          
          --Adds values to update to staging table
          insert into dbo.StageUpdates
          VALUES
              (348923, 95)
              ,(348924, 90)
              ,(348925, 100)
          
          --Update values
          update dbo.MyTable
          set Field1 = NewValue
          from dbo.MyTable as mt
              inner join dbo.StageUpdates as su on mt.ID = su.ID
          where su.NewValue <> mt.Field1 --Modify this if either value can be null.
          
          --Clear updated values from stage
          delete from dbo.StageUpdates
          from dbo.StageUpdates as su
              inner join dbo.MyTable as mt on su.ID = mt.ID
          where su.NewValue <> mt.Field1 --Modify this if either value can be null.
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-02-21
            • 2022-09-23
            • 2022-08-24
            • 2022-01-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-10-29
            相关资源
            最近更新 更多