Performance

在 SQL 數據庫中,更新是重寫行中的所有列還是只重寫 SET 元組中的列?

  • December 21, 2019

我想知道 sql 更新如何在兩種情況下工作:

具有 3 列的表:a, b, c

說必須更改 a 的數據值。

1:更新設置所有列的行a, b, c(其中 b 和 c 與儲存的內容沒有變化)

2:更新一行只設置a列值(因為b和c沒有改變)

這些之間有什麼性能差異嗎?我很難找到有關他們在幕後實際工作的資訊。從我發現的幾篇文章中,我的理解是,在更新中,數據庫將:

  • 將行(所有列)載入到記憶體中
  • 從設置的元組中設置值(按順序)
  • 寫回更新的行

這在數據庫之間會有所不同,但我們可以說通常(但肯定不總是)適用於 SQL Server、Postgres 等常見數據庫。

驅動器 IO 通常以塊為單位工作,現在通常為 4Kbyte 或 0.5K,並且要寫入任何塊,驅動器將寫入整個塊。數據庫引擎出於各種原因將其結構組織成頁面,包括對 IO 子系統進行處理。在 MS SQL Server 中,每頁為 8K,已完成的數據庫允許您在每個 DB 或每個伺服器的基礎上進行選擇。與寫入頁面的底層驅動器一樣,將導致重寫整個頁面(可能是多個磁碟塊大小),而不僅僅是構成更新行的部分或行中的各個列。SET a因此,在您的兩個範例( & )中將完成相同數量的 IO SET a, b, c

事實上,不僅僅是那個頁面會受到影響:首先會在事務日誌中創建一個條目,並且相關的索引頁面也可能需要更新。某些數據庫系統使用(或作為選項支持)的 MVCC 模型作為問題的額外細節,但該細節可能比您的問題的預期範圍更深一些。

另一點似乎確實相關的是,即使沒有真正改變,這個 IO 也會發生:如果你看到a42 列並且它已經是 42,寫入仍然會發生。此外,任何相關的觸發器仍將觸發,將檢查約束等。這就是為什麼您有時會看到類似UPDATE someTable SET aColumn = @aValue WHERE aColumn <> @aValue, 的語句以避免過度活動(如果在您的程式碼中這樣做,請務必小心考慮 NULL,如果它們可能存在,我的範例不是為了簡潔起見,還請注意,在某些情況下,您可能希望觸發觸發器,即使更新實際上沒有執行任何操作)。

在完成這個答案之前,值得重申的是,這對於所有數據庫或更一般的所有 IO 都不是正確的,而只是普遍正確的。

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