2

我有以下查询,我想知道 CASE 构造有多糟糕,它强制 DB 引擎用 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;

也许将这个更新分成两个更新更便宜:

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;
4

3 回答 3

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

于 2011-07-13T20:08:17.360 回答
1

即使值没有改变,更新一行也只需要很少的资源。您可以通过检查更改来施加更多负载。当您的系统高度精炼并且您接近边缘时,您可能会考虑这样的优化,但它会在列表中排名靠后。

于 2011-07-13T20:02:57.160 回答
0

您在表上使用的 SQL Server 功能越多,开销就越大,即使使用无操作 UPDATE 也是如此。

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

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

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

于 2011-07-13T19:44:55.840 回答