【问题标题】:Speed Impact of a WHERE Clause in a SQL UpdateSQL 更新中 WHERE 子句的速度影响
【发布时间】: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”。有什么办法可以把我的话题移到那里吗?
  • 它将排除列为空的行。如果该列上有索引,这实际上可能会使其更快。如果它不能为空,那么我同意它不会有所作为。如果删除它,数据库将需要更新所有行,如果保留它,它还需要更新所有行。主要的性能“问题”通常是实际更新,而不是找到行

标签: sql performance db2 where-clause


【解决方案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 没有“真实”条件。
    猜你喜欢
    • 2015-06-04
    • 2014-02-19
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 1970-01-01
    • 2014-02-08
    • 2016-07-10
    • 2015-05-31
    相关资源
    最近更新 更多