Sql-Server

對錶進行大的更改有什麼更好的方法:每次都刪除和插入或更新現有?

  • May 17, 2016

我正在做一個項目,我需要每天在一張桌子上更改大約 36K 條記錄。我想知道什麼會表現得更好:

  1. 刪除行並插入新行,或
  2. 更新已經存在的行

對我來說,刪除所有行並插入新行更容易,但如果這會使表和索引碎片化並影響性能,那麼我寧願在可能的情況下進行更新並僅在必要時刪除/插入。

這將是一項夜間服務,我不希望提高流程本身的速度。一般來說,我更關心對這個表的查詢性能,我已經有 8900 萬條記錄,以及這個夜間過程將如何影響它。

我應該刪除/插入記錄還是應該更新現有記錄(在可能的情況下)這個夜間流程?

這實際上取決於有多少數據正在發生變化。假設這張表有 20 列。而且您還有 5 個索引 - 每個索引都有一個差異。柱子。

現在,如果所有 20 列中的值都在更改,或者即使 5 列中的數據正在更改並且這 5 列都已編入索引,那麼“刪除和插入”可能會更好。但是,如果只有 2 列正在更改,並且假設它們不是任何非聚集索引的一部分,那麼您最好“更新”記錄,因為在這種情況下,只會更新聚集索引(並且索引不必被更新)。


在進一步的研究中,我確實發現我的上述評論有點多餘,因為 SQL Server 內部有 2 個單獨的機制來執行更新。- “就地更新”(即通過將列值更改為原始行中的新值)或“非就地更新”(DELETE 後跟 INSERT)。

就地更新是規則,並在可能的情況下執行。在這裡,行在相同範圍內的同一頁面上完全保持在同一位置。只有受影響的字節被更改。tlog 只有一條記錄(假設沒有更新觸發器)。如果正在更新堆(並且頁面上有足夠的空間),則會發生更新。如果群集鍵更改但行根本不需要移動,也會發生更新。

例如:如果您有一個姓氏的聚集索引並且您有以下名稱:Able、Baker、Charlie 現在您想將 Baker 更新為 Becker。不必移動任何行。所以這可以就地進行。然而,如果您必須將 Able 更新為 Kumar,則必須移動行(即使它們位於同一頁面上)。在這種情況下,SQL Server 將執行 DELETE,然後執行 INSERT。

考慮到上述情況,我建議您執行正常的 UPDATE 並讓 SQL Server 找出如何在內部執行此操作的最佳方法。

有關“更新”內部或任何與 SQL Server 相關的內部的更多詳細資訊,請查看 Kalen Delaney、Paul Randal 等人的書 - SQL Server 2008 Internals

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