SQL Server:是否值得在更新前檢查欄位中的更改?
我正在調查 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
如果您使用繁重的檢查,也許是您無法以某種方式從
SET
and子句中排除的子查詢WHERE
¹,那麼那裡的額外工作可能會使不必要更新的額外 IO 相形見絀。$$ 1 $$CTE 通常是對此的答案,儘管並非總是如此,並且查詢規劃器可能足夠聰明,不會兩次執行相同的子查詢,但我不想對此進行回复。
$$ 2 $$因為 NULL 不僅不等於 NULL,而且也不等於 NULL。