Sql-Server

SQL Server 更新語句加入索引列

  • August 6, 2019

使用 SQL Server 2012,我有一個儲存過程,它通過執行類似於以下的刪除和插入來更新數據:

DELETE  FROM MyTable
WHERE   EXISTS (   SELECT   1
                  FROM     StagingMyTable s
                  WHERE    MyTable.ID = s.ID
                           AND MyTable.ID2 = s.ID2)

INSERT INTO MyTable
SELECT  *
FROM    StagingMyTable

已更改為更新和插入過程,如下所示:

UPDATE  mt
SET     mt.ID = s.ID
     , mt.ID2 = s.ID2
     , mt.col1 = s.col1
     , mt.col2 = s.col2  /* Rest of the columns here*/
FROM    MyTable        mt
JOIN    StagingMyTable s ON mt.ID = s.ID
       and mt.ID2 = s.ID2


INSERT INTO MyTable
SELECT  *
FROM    StagingMyTable s
WHERE   NOT EXISTS (   SELECT   1
                      FROM     MyTable
                      WHERE    MyTable.ID = s.ID
                               AND MyTable.ID2 = s.ID2)

MyTable 在 ID 和 ID2 列上有一個聚集索引,這就是我們決定更新儲存過程以更新和插入的原因。我想知道的是我是否應該在更新語句中省略兩個關鍵列,即使這些值沒有被更改,即

UPDATE  mt
SET     mt.col1 = s.col1
     , mt.col2 = s.col2  /* Rest of the columns here*/
FROM    MyTable        mt
JOIN    StagingMyTable s ON mt.ID = s.ID
                        and mt.ID2 = s.ID2

如果我在更新語句中包含鍵列,SQL Server 是否認為這些將是新值並刪除並重新插入行?

SQL Server 可能會根據許多因素選擇執行就地更新或插入和刪除,您不必擔心。由於沒有更新密鑰,我會將它們排除在 SET 子句之外,以幫助優化器做出最佳決策。

如果您使用的是 SQL Server 2008 或更高版本,請查看可以替換這兩個操作的 MERGE 語句: https ://docs.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql?view =sql-server-2017

高溫高壓

如果ID and ID2列是關鍵列,那麼您需要擔心錯誤的更新語句。

同意,those values aren't being changed但它創建了非常昂貴的查詢計劃。

事實上,您應該 mt.col1 = s.col1 , mt.col2 = s.col2在 Update your Self 中比較有無查詢計劃。

Begin Tran

UPDATE  mt
SET     mt.col1 = s.col1
     , mt.col2 = s.col2  /* Rest of the columns here*/
FROM    MyTable        mt
JOIN    StagingMyTable s ON mt.ID = s.ID
                        and mt.ID2 = s.ID2

If (@@TranCount>0)
RollBack

您會注意到拆分運算符,它是 拆分排序折疊模式的一部分

如果我在更新語句中包含鍵列,SQL Server 是否認為這些將是新值並刪除並重新插入行?

是的,這樣Execution plan顯示split-sort-collapse。執行計劃中有一個操作員完全相同(刪除並重新插入行)。

引用自:https://dba.stackexchange.com/questions/244519