我們已棄用某個功能並正在清除一些數據。在完全刪除需要太多即時應用程序開發的列之前,我們只需簡單清除其包含的數據(應用程序支持的數據)。可能拖延UPDATE x SET y = NULL語句
但是,一個簡單的UPDATE foo SET bar = NULL
似乎異常昂貴。在數據庫的測試副本中,在我們取消它之前,它運行了三個多小時。
我們再次嘗試使用表鎖和READ UNCOMMITTED
隔離級別進行查詢,但無濟於事(在另外三個小時後取消)。
該表包含大約112000行,每行的列包含大約41400字節(所以我們正在清除大於4GiB的數據)。雖然它有相當多的數據,但我們發現將剩餘列複製到新表中,刪除舊錶並重新命名新表會實際上更快。請注意,我們不知道要花多少時間才能完成UPDATE
,否則我們在3小時後停止,但可能每天5,6,12。
該表在這些操作過程中的併發訪問精確度爲零。
有人會對我們的方案有任何建議嗎? copy + drop + rename是否是最好的選擇?如果是的話,還有什麼特別的建議使它儘可能安全?
對我們來說,一個可能天真的假設是DBMS將能夠在正常的UPDATE
聲明的幕後制定一個複製/交換策略,如果給出足夠鬆散的提示。可能嗎?
看起來像記錄事務的典型案例比您預期的要貴。嘗試使用循環來更新塊,例如1000,一次一排。 – HABO
@HABO聽起來不錯,謝謝。看看[this](https://social.msdn.microsoft.com/Forums/sqlserver/en-US/90a44905-f3e3-4f82-9c83-e875a1bf1cb1/this-would-be-a-great-addition-to- tsql)似乎沒有一種「好」的方式去實現它(即不需要每個批次掃描表)。使用我們的謂詞('bar IS NOT NULL')進行掃描需要很多時間(已經7分鐘並且計數,這取決於批量的數量會非常快)。我的猜測是由於列的大小,數據不在行中內聯。你知道分裂這種交易的慣用方法嗎? – tne
一個常見的方法就像'update ...',其中FooId(從Foo中選擇頂部1000 FooId,其中Bar不是NULL)'循環,直到'@@ RowCount'爲零。在你的情況下,在臨時表中收集適當的'FooId'並解決這個問題以避免重新掃描'Foo'是有意義的。在處理它們時刪除或標記臨時錶行。並且嘗試不同的塊大小沒有壞處,例如100行,直到找到(相對)最佳位置。 – HABO