SQL 更新中 WHERE 子句的速度影响
Posted
技术标签:
【中文标题】SQL 更新中 WHERE 子句的速度影响【英文标题】:Speed Impact of a WHERE Clause in a SQL Update 【发布时间】:2016-04-12 07:51:58 【问题描述】:我在 DB2 (IBM System I) 表上有一个非常简单的 SQL 更新命令,该表包含大约 . 3000 万条记录。
UPDATE tablename SET field = 0 where field > 0
现在,鉴于该字段永远不能是并且不可为空,“where”子句不是不必要的吗? WHERE 子句是否会影响此过程的持续时间?
据我了解,这是不必要的,并且会影响速度,因为数据库必须评估每条记录。我正试图找出这一点,因为我自己无法运行 SQL,而我们的分包商说它没有影响;而且我们没有知识来证明/证伪这一点。
【问题讨论】:
一次更新3000万条记录? 列field
是否已编入索引?如果是,可能根本没有区别,如果不是,可能是很小的区别。
是的,一次更新 3000 万条记录。不,据我所见,该字段未编入索引。
ps:我刚刚看到“数据库管理员”有一个特殊的子“stackexchange”。有什么办法可以把我的话题移到那里吗?
它将排除列为空的行。如果该列上有索引,这实际上可能会使其更快。如果它不能为空,那么我同意它不会有所作为。如果删除它,数据库将需要更新所有行,如果保留它,它还需要更新所有行。主要的性能“问题”通常是实际更新,而不是找到行
【参考方案1】:
如果field
的列类型可以为 NULL,它确实会产生影响。在field > 0
中,NULL 将评估为 false。如果仅在您获得一些数据后才将字段设置为一个值,即假设该字段表示今天发送的电子邮件,而原始 DBA 让field
为空,即Unknown
。如果你运行这个
UPDATE tablename SET field = 0;
每个人都会被重置,您将无法查明有多少人从未发送过电子邮件,例如。
select count(*) from tablename where field = NULL
因此,根据您的架构和语义,它可能意味着很多。请注意,这是一个示例,我并不是说它是一个好的设计或 NULL 的好用处。
【讨论】:
【参考方案2】:结论:如果字段列不为0,则where在运行时只有很小的差异。 如果有几个 0 很快就会变得更快 where 子句很快就会在速度上获胜,如果字段列中可能存在 0,则 imo 应该始终在查询中
我创建了一个有 4.967.877 行的 db 表。
我用 0 填充了一半的行,另一半用 1 填充
UPDATE HugeDummyTable
SET field = 0
WHERE HugeDummyTableID < 2483938
UPDATE HugeDummyTable
SET field = 1
WHERE HugeDummyTableID >= 2483938
带有 where 的查询:
SET STATISTICS TIME ON
UPDATE HugeDummyTable SET field = 0 where field > 0
给出结果:
SQL Server Execution Times:
CPU time = 1829 ms, elapsed time = 1842 ms.
(2483940 row(s) affected)
使用相同的第一个查询重置表。 在没有 where 的情况下进行查询
SET STATISTICS TIME ON
UPDATE HugeDummyTable SET field = 0
给出这个结果:
SQL Server Execution Times:
CPU time = 2765 ms, elapsed time = 2791 ms.
(4967877 row(s) affected)
所以我认为 where 使查询更快。
在 cmets 之后编辑:用随机数填充“字段”列 为了确保我将在 2 次尝试中使用同一张表,我进行了备份。
Update HugeDummyTable
SET field = ABS(Checksum(NewId()) % 100000)
看看我有多少个 0:
SELECT COUNT(field)
FROM HugeDummyTable
WHERE field = 0
"45"
使用 where 运行查询:
SET STATISTICS TIME ON
UPDATE HugeDummyTable SET field = 0 where field > 0
SQL Server Execution Times:
CPU time = 3313 ms, elapsed time = 3325 ms.
(4967829 row(s) affected)
已恢复的表,没有 where 重新运行:
SET STATISTICS TIME ON
UPDATE HugeDummyTable SET field = 0
SQL Server Execution Times:
CPU time = 3094 ms, elapsed time = 3121 ms.
(4967877 row(s) affected)
差异较小,但仍然存在。 where 似乎切断了一点时间,即使只有 45 条记录的差异。
编辑 2:测试时没有 0
这次字段列没有0 没有哪里
SQL Server Execution Times:
CPU time = 3109 ms, elapsed time = 3238 ms.
在哪里
SQL Server Execution Times:
CPU time = 3172 ms, elapsed time = 3337 ms.
【讨论】:
谁能解释一下为什么会这样? 在运行基准测试之前,您应该使用1s
和0s
随机化记录的顺序。
@Jordumus 如果您使用 where 子句,您将更新一半的行数。
@SeanPearce 是的,所以事实上,这个测试并不是 OP 所要求的。因为 OP 没有“真实”条件。以上是关于SQL 更新中 WHERE 子句的速度影响的主要内容,如果未能解决你的问题,请参考以下文章