效率更新在哪里......与案例......时间

时间:2017-03-22 16:00:29

标签: sql sql-server tsql

对于大表(约5百万行),更新所有符合条件的行(大约1000行)更有效:

1。一个简单的更新声明?

UPDATE table SET last_modif_date = NOW() WHERE condition; 

2. 如果条件匹配

,则执行更新的情况
UPDATE table SET
last_modif_date = (CASE WHEN CONDITION THEN NOW() ELSE last_modif_date END)

为什么?

提前致谢

4 个答案:

答案 0 :(得分:3)

我做了一个简单的测试 - 结果是where版本比case版本效率更高。
这是我做过的测试:

/*

-- Create a numbers (tally) table if you don't already have one
SELECT TOP 10000 IDENTITY(int,1,1) AS Number
    INTO Tally
    FROM sys.objects s1       
    CROSS JOIN sys.objects s2 
ALTER TABLE Tally ADD CONSTRAINT PK_Tally PRIMARY KEY CLUSTERED (Number)

*/


-- Create a dates table with 10000 rows
SELECT Number As Id, DATEADD(DAY, Number, DATEADD(DAY, -5000, GETDATE())) As TheDate
INTO DatesTest
FROM Tally

-- Update using a where clause 
UPDATE DatesTest 
SET TheDate = GETDATE()
WHERE Id % 100 = 0

-- Drop and re-create the same dates table
DROP TABLE DatesTest

SELECT Number As Id, DATEADD(DAY, Number, DATEADD(DAY, -5000, GETDATE())) As TheDate
INTO DatesTest
FROM Tally

-- Update using case
UPDATE DatesTest 
SET TheDate = CASE WHEN Id % 100 = 0 THEN GETDATE() ELSE TheDate END

从执行计划中可以看出 - where子句版本仅占所有执行成本的7%,而案例版本为34%。
我会说我们有一个胜利者。

enter image description here

答案 1 :(得分:2)

一般的最佳做法不是updatedelete没有where条款,因为人们会犯错误并从其中一些中恢复可能是一个真正的痛苦。

除此之外,即使是非更新的更新也会对数据库产生重大影响,而不仅仅是性能较差的查询。在没有update的情况下执行where也可能导致过度锁定和阻止其他并发操作。

我无法总结这篇文章比保罗怀特为自己做的更好,这里还有一些事情需要考虑:

  

SQL Server包含许多优化,以避免在处理不会导致持久数据库发生任何更改的UPDATE操作时出现不必要的日志记录或页面刷新。

     
      
  • 对群集表的非更新更新通常会避免额外的日志记录和页面刷新,除非构成(部分)群集密钥的列受更新操作的影响。
  •   
  • 如果群集密钥的任何部分被“更新”为相同的值,则记录操作,就像数据已更改一样,并且受影响的页面在缓冲池中标记为脏。这是将UPDATE转换为delete-then-insert操作的结果。
  •   
  • 堆表的行为与群集表的行为相同,除了它们没有群集键以导致任何额外的日志记录或页面刷新。即使堆上存在非群集主键,情况仍然如此。因此,对堆的非更新更新通常会避免额外的日志记录和刷新(但请参见下文)。
  •   
  • 对于包含超过8000个字节数据的LOB列使用除“SET column_name = column_name”以外的任何语法更新为相同值的任何行,堆和聚簇表都将遭受额外的日志记录和刷新。
  •   
  • 只需在数据库上启用任一类型的行版本控制隔离级别,都会导致额外的日志记录和刷新。无论更新事务的有效隔离级别如何,都会发生这种情况。   〜The Impact of Non-Updating Updates - Paul White
  •   

答案 2 :(得分:1)

结果是不同的,因为带有CASE的UPDATE SET将更新所有行,并且会在更新时触发,依此类推,如果在您的情况下,您的新值实际上是之前的值。

带有WHERE子句的UPDATE将仅更新您真正想要更新的行,并仅在这些行上触发。假设你有一个索引,在大多数情况下效率更高。

您唯一可以确定的方法是分析两个查询的实际执行计划并进行比较。无论如何,在UPDATE WHERE上使用UPDATE SET CASE有点不自然。

答案 3 :(得分:0)

通常,'其中'条款比“案例”更有效率。如果您正在使用的列上有索引,则为statement。 '案例'语句将使查询(搜索)顺序,这意味着将检查每一行的条件。列上具有索引的Where子句(可以在您应用的条件下使用),将仅扫描记录的子集并使用更快的搜索算法(在大多数情况下)。

底线是实际查询(您正在使用的条件),索引可以在语句的性能上产生很多差异。分析查询的最佳方法是在SQL Server管理工作室中使用查询的执行计划。

您可以阅读此帖子以了解有关执行计划的更多信息: https://www.simple-talk.com/sql/performance/execution-plan-basics/