更新声明的性能问题

Performance Concern for Update Statement

我的更新流程如下:

UPDATE Repairs
SET TypeID = CASE WHEN @TypeID IS NULL THEN TypeID ELSE @TypeID END,
    Directions = CASE WHEN @Directions IS NULL THEN Directions ELSE @Directions END,
    LastUpdate = SYSDATETIME()
WHERE RepairID = @RepairID

我没有并发问题,但 Directions 可能是一个很长的 NVarChar 字符串。 SQL 服务器是否足够智能,不会将现有数据复制到自身,还是我应该寻找其他方法?

这可以改写如下:

UPDATE Repairs
SET
    TypeID = ISNULL(@TypeID, TypeID),
    Directions = ISNULL(@Directions, Directions),
    LastUpdate = SYSDATETIME()
WHERE RepairID = @RepairID;

但这不会产生任何显着差异。如果只是这几列,那么您可能有三种不同的情况来进行这些更新:

IF @TypeID IS NOT NULL
AND @Directions IS NOT NULL
    UPDATE Repairs
    SET
        TypeID = ISNULL(@TypeID, TypeID),
        Directions = ISNULL(@Directions, Directions),
        LastUpdate = SYSDATETIME()
    WHERE RepairID = @RepairID;
ELSE IF @TypeID IS NOT NULL
    UPDATE Repairs
    SET
        TypeID = ISNULL(@TypeID, TypeID),
        LastUpdate = SYSDATETIME()
    WHERE RepairID = @RepairID;
ELSE IF @Directions IS NOT NULL
    UPDATE Repairs
    SET
        Directions = ISNULL(@Directions, Directions),
        LastUpdate = SYSDATETIME()
    WHERE RepairID = @RepairID;
ELSE
    THROW 51000, 'Nothing to update mate!', 1;

但我怀疑这是否也会产生重大影响。它只是为您的代码添加了太多样板。保持现有或 ISNULL()s

Is SQL Server smart enough not to copy the existing data onto itself Yes it is smart enough.

当您修改一行时,SQL 服务器仅记录修改后的字节,因此例如当您将 int 值从 1 更改为 24 时,SQL 服务器仅修改 4 ( int 值是 4 个字节长)

所做的更改可以以两种方式写入日志,如LOP_MODIFY_ROWLOP_MODIFY_COLUMNS,但无论如何如果你的nvarchar值没有改变,只有行的固定长度部分会被记录(您更改的其他字段为定长类型)

如果您的字符串是 nchar(而不是 nVARchar),情况可能会有所不同,在这种情况下,table 定义中的列顺序很重要。

如果您没有修改 LastUpdate,则根本不会记录任何内容。

如果您的问题不是关于日志记录而是关于数据页,当然如果一行有任何更改(并且您总是至少修改 LastUpdate 字段),该页会立即被标记为脏页。这意味着此页面与存储在磁盘上的页面不同,下一个检查点操作会将其写入磁盘。

SQL 服务器并没有将每一个修改的行都写入磁盘,可以写入磁盘的最小数据量是一个页面(8Kb),但是并没有立即写入磁盘修改后,它是定期将脏页写入磁盘的检查点(好吧,或者是急切的写入器,或者准确地说是懒惰的写入器)。