Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server Update语句的性能问题_Sql Server_Sql Update_Query Performance - Fatal编程技术网

Sql server Update语句的性能问题

Sql server Update语句的性能问题,sql-server,sql-update,query-performance,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 UPDATE Repai

我有如下更新程序:

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
UPDATE Repairs
SET
    TypeID = ISNULL(@TypeID, TypeID),
    Directions = ISNULL(@Directions, Directions),
    LastUpdate = SYSDATETIME()
WHERE RepairID = @RepairID;

我没有并发问题,但是
Directions
可能是一个相当长的
NVarChar
字符串。SQL Server是否足够聪明,不会将现有数据复制到自身,或者我是否应该寻找另一种方法?

这可以重写如下:

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

这可以重写如下:

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

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

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

所做的更改可以通过两种方式写入日志,即
LOP\u MODIFY\u ROW
LOP\u MODIFY\u COLUMNS
,但无论如何,如果您的nvarchar值没有更改,则只会记录行的固定长度部分(您更改的其他字段属于固定长度类型)

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

若你们并没有修改LastUpdate,那个么根本就并没有日志记录

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

SQL Server并没有将每一个修改的行写入磁盘,可以写入磁盘的最小数据量是一页(8Kb),但它不会在修改后立即写入磁盘,而是定期将脏页写入磁盘的检查点(ok,或者确切地说是热切写入器,或者是懒惰写入器)

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

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

所做的更改可以通过两种方式写入日志,即
LOP\u MODIFY\u ROW
LOP\u MODIFY\u COLUMNS
,但无论如何,如果您的nvarchar值没有更改,则只会记录行的固定长度部分(您更改的其他字段属于固定长度类型)

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

若你们并没有修改LastUpdate,那个么根本就并没有日志记录

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


SQL Server并没有将所有修改的行写入磁盘,可以写入磁盘的最小数据量为一页(8Kb),但它并不是在修改后立即写入磁盘,而是检查点(准确地说,是“ok”,或“急切写入器”,或“惰性写入器”)定期将脏页写入磁盘。

即使没有任何更改,您是否希望更新最后一个更新列?我觉得这是一个过早的优化。您是否已经对此进行了测试和测量,并确定存在性能问题?@MartinSmith这是在一个存储过程中,除非至少有一个输入变量不为null,否则将不会调用该存储过程。是否希望即使没有任何更改,也能更新最后一个更新列?我觉得这是一个过早的优化。您是否已经对其进行了测试和测量,并确定存在性能问题?@MartinSmith这是一个存储过程,除非至少有一个输入变量不为null,否则不会调用该存储过程。不,我不关心日志记录。您回复的第二部分是我一直在寻找的,因此我将此标记为答案。好的,尽管我建议考虑日志记录,因为这可能是性能问题:更新始终是一个完全记录的操作,这意味着在提交之前,日志缓冲区会写入磁盘,并且是一个I\O操作。所以,当您在1000个事务中更新1000行时,将至少有1000个日志写入磁盘,而根本无法写入数据文件。不,我不关心日志记录。您回复的第二部分是我一直在寻找的,因此我将此标记为答案。好的,尽管我建议考虑日志记录,因为这可能是性能问题:更新始终是一个完全记录的操作,这意味着在提交之前,日志缓冲区会写入磁盘,并且是一个I\O操作。因此,当您在1000个事务中更新1000行时,将至少有1000个日志写入磁盘,而在allI上则无法写入数据文件。我没有想过使用更简单的样式来检查空值。我并不声称自己有很多SQL代码,所以这很有帮助。我没有想过使用更简单的样式来检查空值。我并不声称自己有很多SQL排版,所以这是有帮助的。