代码之家  ›  专栏  ›  技术社区  ›  SezMe

更新声明的性能问题

  •  0
  • SezMe  · 技术社区  · 7 年前

    我有一个更新过程如下:

    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 回复  |  直到 7 年前
        1
  •  2
  •   sepupic    7 年前

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

    所做的更改可以通过两种方式写入日志,如下所示: LOP_MODIFY_ROW 或作为 LOP_MODIFY_COLUMNS

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

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

    SQL Server并不是将每一个修改的行写入磁盘,可以写入磁盘的最小数据量是一个页面(8Kb),但它并不是在修改后立即写入磁盘,而是定期将脏页写入磁盘的检查点(ok,确切地说是eager writer,或lazy writer)。

        2
  •  1
  •   Evaldas Buinauskas    7 年前

    这可以重写如下:

    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()