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.    

【讨论】:

谁能解释一下为什么会这样? 在运行基准测试之前,您应该使用1s0s 随机化记录的顺序。 @Jordumus 如果您使用 where 子句,您将更新一半的行数。 @SeanPearce 是的,所以事实上,这个测试并不是 OP 所要求的。因为 OP 没有“真实”条件。

以上是关于SQL 更新中 WHERE 子句的速度影响的主要内容,如果未能解决你的问题,请参考以下文章

SQL where 条件顺序对性能的影响有哪些

调用视图的查询中的 where 子句是不是会影响视图本身的过滤器?

WHERE 子句中的字段顺序会影响 MySQL 的性能吗?

SQL 问题:WHERE 子句的顺序有区别吗?

SQL on&where&having

where条件放在子SQL语句中是否查询速度更快?