Sql-Server

SQL Server:是否值得在更新前檢查欄位中的更改?

  • May 14, 2022

我正在調查 SQL Server 2019 上的語句性能(我已經提取了重要部分):

  UPDATE 
       m
  SET
       A1 = src.A1,
       A2 = src.A2,
       A3 = src.A3,
       A4 = src.A4,
       A5 = src.A5
  FROM 
     MyTable m 
     JOIN SourceTable src ON m.Id = src.Id
  WHERE 
       A1 <> src.A1
   OR  A2 <> src.A2
   OR  A3 <> src.A3
   OR  A4 <> src.A4
   OR  A5 <> src.A5
  • 沒有觸發器
  • 行數相當少(大約 200k-300k)
  • 主要是從表中讀取,但經常
  • A1/5 不在索引下,它們大多是 nvarchar(50) 或類似的
  • 無複製設置

WHERE做部分來防止不必要的更新是否值得?如果不是 - 哪個案例值得?

做 WHERE 部分來防止不必要的更新是否值得?

是的。即使實際上沒有任何更改,對行的每次更新都會導致寫入日誌和數據文件。這種額外的 IO 負載可能會直接影響性能。它還可能需要更多的鎖,這可能會進一步損害並發性,包括您的讀取,而不僅僅是其他寫入。

除了由寫入本身引起的額外 IO 之外,還可能有其他連鎖反應:如果您正在為備份進行日誌傳送,那麼您將在那裡使用更多的空間和頻寬。差異備份也可能比它們原本需要的更大。當然,如果您使用複制、鏡像等,這些 NoOp 寫入也將在那裡生效。

此外,如果您使用時態表,您會在歷史記錄中找到額外的一行,因此您也會以這種方式消耗更多空間,可能是永久的。

沒有觸發器/沒有複製設置

如果您現在沒有使用上述任何一種,您可能會選擇稍後使用。或者你之後的某個人。

A1/5 不在索引下,它們大多是 nvarchar(50) 或類似的

這些是否被索引不應影響寫入決定的性能。

行數相當少(大約 200k-300k)

請始終注意,您的數據可能會隨著時間的推移而顯著增長。

如果不是 - 哪個案例值得?

正如我所說的那樣,大多數時候它絕對值得,我將把這個問題轉為“哪個案例會讓它值得?”:

對於您可以不關心上述任何內容的小型更新,如果您不包含過濾子句,您的程式碼會簡單得多。如果生成的過濾子句又長又復雜,那麼這將消除奇怪錯誤的潛在來源。如果受影響的列可以為空,則您的WHERE子句範例可能需要更複雜/更醜陋,因此可能已經存在錯誤,因為如果其中一個為 NULL 但另一個不是,A1 <> src.A1則可能使其跳過更新²。m.A1``src.A1

如果您使用繁重的檢查,也許是您無法以某種方式從SETand子句中排除的子查詢WHERE¹,那麼那裡的額外工作可能會使不必要更新的額外 IO 相形見絀。

$$ 1 $$CTE 通常是對此的答案,儘管並非總是如此,並且查詢規劃器可能足夠聰明,不會兩次執行相同的子查詢,但我不想對此進行回复。

$$ 2 $$因為 NULL 不僅不等於 NULL,而且也不等於 NULL。

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