对于大表(约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)
为什么?
提前致谢
答案 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%。
我会说我们有一个胜利者。
答案 1 :(得分:2)
一般的最佳做法不是update
或delete
没有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/