繁体   English   中英

效率更新地点……案例……何时

[英]Efficiency UPDATE WHERE … vs CASE … WHEN

对于大表(约500万行),更新所有符合条件的行(约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)

又为什么呢?

提前致谢

我做了一个简单的测试-结果是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%。
我会说我们有赢家。

在此处输入图片说明

一般的最佳做法是不带where子句而不updatedelete where因为人们会犯错误,从错误中恢复可能是真正的痛苦。

除此之外,即使是不更新的更新也可以对数据库产生重大影响,而不仅仅是性能低下的查询。 不使用where执行update也可能导致过多的锁定和其他并发操作的阻塞。

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

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

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

结果只是不同,因为使用CASE的UPDATE SET将更新所有行,并在更新时触发,以此类推,即使在您的情况下您的新值实际上是先前值也是如此。

使用WHERE子句的UPDATE将仅更新您真正想要更新的行,并且仅在这些行上触发。 假设您有一个索引,则在大多数情况下它会更有效。

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM