对更新声明的性能关注

时间:2017-07-29 18:18:59

标签: sql-server sql-update query-performance

我的更新程序如下:

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 Server足够聪明,不会将现有数据复制到自身上,还是应该寻找其他方法?

2 个答案:

答案 0 :(得分:2)

  

SQL Server是否足够智能,不会将现有数据复制到自身   是的,它足够聪明。

当您修改行时,SQL Server仅记录修改的字节,因此当您将int值从1更改为24时,SQL Server仅修改1个字节的4(int值为4个字节长)

所做的更改可以用两种方式写入,如mLayoutManager.smoothScrollToPosition(mRecyclerView, null, array.size() - 1); LOP_MODIFY_ROW,但无论如何,如果你的nvarchar值没有改变,那么只记录行的固定长度部分(您更改的其他字段是固定长度类型)

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

如果你没有修改LastUpdate,根本就没有任何日志记录。

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

SQL Server没有将每个修改过的行写入磁盘,可以写入磁盘的最小数据量是一个页面(8Kb),但是一旦修改它就不会立即写入磁盘,而是检查点(好的,或急切的写作者,或者说是精确的懒惰的写作者,定期将脏页写入磁盘。

答案 1 :(得分:1)

这可以改写如下:

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