根据条件更新多个列,哪种方法性能更好,或者是不是有其他更好的方法

Posted

技术标签:

【中文标题】根据条件更新多个列,哪种方法性能更好,或者是不是有其他更好的方法【英文标题】:Update multiple columns based on condition which approach is better in performance or is there any other better approach根据条件更新多个列,哪种方法性能更好,或者是否有其他更好的方法 【发布时间】:2020-10-08 09:43:36 【问题描述】:
drop table #source
create table #source
(
    userid int NULL,
    col1 nvarchar(max) NULL,
    col2 nvarchar(max) NULL,
    col3 nvarchar(max) NULL,
)
drop table #target
create table #target
(
    userid int NULL,
    col1 nvarchar(max) NULL,
    col2 nvarchar(max) NULL,
    col3 nvarchar(max) NULL,
    col4 nvarchar(max) NULL,
)
insert into #source values(1,'A','','B')
insert into #source values(2,'a',NULL,'b')

insert into #target values(1,NULL,'B','','extra')
insert into #target values(2,'aa',NULL,'b','extra')

select * from #source
select * from #target

update #target 
   set col1 = s.col1,
       col2 = s.col2,
       col3 = s.col3
   from #target t
   inner join #source s
     on s.userid = t.userid
where 
    s.col1 <> t.col1 or s.col1 is null and t.col1 is not null or s.col1 is not null and t.col1 is null
OR  s.col2 <> t.col2 or s.col2 is null and t.col2 is not null or s.col2 is not null and t.col2 is null
OR  s.col3 <> t.col3 or s.col3 is null and t.col3 is not null or s.col3 is not null and t.col3 is null


update #target 
   set 
       col1 = CASE WHEN s.col1 <> t.col1 or s.col1 is null and t.col1 is not null or s.col1 is not null and t.col1 is null THEN s.col1 ELSE t.col1 END,
       col2 = CASE WHEN s.col2 <> t.col2 or s.col2 is null and t.col2 is not null or s.col2 is not null and t.col2 is null THEN s.col2 ELSE t.col2 END,
       col3 = CASE WHEN s.col3 <> t.col3 or s.col3 is null and t.col3 is not null or s.col3 is not null and t.col3 is null THEN s.col3 ELSE t.col3 END
   from #target t
   inner join #source s
     on s.userid = t.userid

我只想在给定列的值不同时更新,并且还要考虑性能。非常感谢任何见解。提前致谢。看了很多线程,才知道如果值相同,SQL内部不会执行更新。

【问题讨论】:

如果值相同,update 仍会导致更新;尚未在最新版本中对其进行测试,但我非常确信更新不关心值是否更改,无论如何它都会将新版本写入磁盘。无论如何,找出最有效的方法的最简单方法就是尝试一下。 【参考方案1】:
    确保两个表都在 user_id 上(集群)索引。 为所有 ANDOR 添加一些括号,如果只是为了便于阅读。

您的第一个update 将按照您的预期进行:仅更新有差异的记录。第二个update 将更新所有(匹配用户ID)记录。

在性能方面,第一个对于系统来说可能会容易得多,因为实际记录数可能远低于记录总数。

在极端情况下,您可能会争辩说 IF 所有记录都需要更新,那么第二个版本中更简单的INNER JOIN 在系统上可能会稍微容易一些,但在这种情况下,您可以获得摆脱 CASE..WHEN..THEN 构造,因为坦率地说,它并没有真正添加任何东西:当您将字段设置为一个值时,该值是否与以前的值相同并不重要。

【讨论】:

感谢您花时间阅读我的帖子。 dev.mysql.com/doc/refman/8.0/en/update.html line “如果您将列设置为它当前具有的值,MySQL 会注意到这一点并且不会更新它。”请看看这个并分享你的想法。感谢您在这方面的时间。 啊。问题没有提到这是 MySQL。给定 sql-server 标签,我认为它是 MSSQL。我几乎没有使用 MySQL 的经验,很可能是说 RDBMS 以不同的方式处理这个问题。有趣的。我现在想知道这如何/是否会影响受影响的行数...不过,我仍然认为您可以摆脱 CASE..WHEN..THEN 构造,因为直接分配新值将具有完全相同的效果。 (PS:链接的文章还显示UPDATE t1 SET col1 = col1 + 1, col2 = col1; 的行为相当奇特。可怕但我们每天都在学习=) 总而言之,我最好的建议仍然是,解决这个问题的唯一可靠方法是进行一些测试,只需确保您的卷具有“代表性”。在 100 行上效果很好的方法在 100k 行上效果可能会大不相同。 再次感谢。我为混乱道歉。我不应该假设它可能是 MSSQl 中的相同实现。到目前为止,我在 MSSQL 文档中找不到任何内容。我尝试了 250k 行和 11 列。 case 语句耗时 10 秒,没有 case 语句则耗时 7 秒。

以上是关于根据条件更新多个列,哪种方法性能更好,或者是不是有其他更好的方法的主要内容,如果未能解决你的问题,请参考以下文章

在sql server中用一个条件更新多个列

SQL Server 非聚集索引

MySQL 使用多个条件更新列的值

哪种方法在性能方面更好? (关于JDBC中prepared statement中可变参数标记的使用)

根据单个列中的多个条件选择多个列

有条件地创建熊猫列的最快方法