过度更新有多糟糕?

时间:2011-07-13 17:45:30

标签: sql sql-server sql-server-2008 sql-optimization

我有以下查询,我想知道CASE构造有多糟糕,它强制数据库引擎用E.EAOpID中未包含的值覆盖E.EAOpID

UPDATE E
SET E.EAOpID =  CASE
                    WHEN E.EAOpID IS NULL THEN @operationID
                    ELSE E.EAOpID
                END,
    E.AverageCapacity = E.AverageCapacity + 1,
    E.Average = E.Average - (E.Average - E.Value) / E.AverageCapacity
FROM
(
    SELECT E.EAOpID, E.AverageCapacity, E.Average, P.Value
    FROM Probes AS P
    INNER JOIN Estimates AS E ON P.EstimateID = E.ID
    WHERE P.EAOpID = @operationID
) AS E;

将此UPDATE拆分为两个更新可能更便宜:

1

UPDATE E
SET E.EAOpID = @operationID
FROM
(
    SELECT E.EAOpID, E.AverageCapacity, E.Average, P.Value
    FROM Probes AS P
    INNER JOIN Estimates AS E ON P.EstimateID = E.ID
    WHERE   P.EAOpID = @operationID
        AND E.EAOpID IS NULL -- Additional statement here
) AS E;

2

UPDATE E
SET E.AverageCapacity = E.AverageCapacity + 1,
    E.Average = E.Average - (E.Average - E.Value) / E.AverageCapacity
FROM
(
    SELECT E.EAOpID, E.AverageCapacity, E.Average, P.Value
    FROM Probes AS P
    INNER JOIN Estimates AS E ON P.EstimateID = E.ID
    WHERE P.EAOpID = @operationID
) AS E;

3 个答案:

答案 0 :(得分:1)

即使没有更改任何值,更新行也会占用很少的资源。您只需检查更改即可施加更多负载。你可能会考虑在你的系统高度精炼并且接近边缘时考虑这样的优化,但它在列表中会很低。

答案 1 :(得分:1)

两个更新将使用几乎两倍的资源,因为您将读取/更新同一组行。不要在一个查询中包含所有内容。我不知道如何测量case语句需要多少额外处理,但我知道以下使用较少的编码逻辑执行相同数量的工作。从

改变它
UPDATE E
 SET E.EAOpID =  CASE
                     WHEN E.EAOpID IS NULL THEN @operationID
                     ELSE E.EAOpID
                 END, 
 (etc)

UPDATE E
 SET E.EAOpID = isnull(E.EAOpID, @operationID), 
 (etc)

(如果它让您满意,可以使用coalesce代替isnull。)

答案 2 :(得分:0)

您在表上使用的SQL Server的功能越多,即使使用no-op UPDATE也会产生更多的开销。

在索引维护之外执行操作和额外读取。

触发器(触发触发器),外键(仍检查完整性),约束(检查规则)等。

作为示例:向表中添加一个约束,该表将使用某些现有值失败,但使用“WITH NOCHECK”进行创建。将现有列更新为自身;即使值没有改变,更新也会在约束上失败。