針對需要定期截斷的異常數據庫結構調整讀取(或者可能是截斷!)
我們有一個不尋常的數據庫結構(我將推理留給另一個問題),在其目前形式下,需要定期截斷和重新創建大量行(大約 100 萬行)。
我們正在努力重新考慮它。但是,作為一個短期解決方案,在這種情況下是否有任何查詢提示可以提供幫助?
有沒有辦法做到這一點,如果在被截斷/重新填充的表上發生讀取,它會忽略這個事實,即它只會在截斷開始之前讀取數據?
我們試圖避免鎖定(我們認為)。
我意識到這不是一個長期的解決方案,而是尋找可能的解決方案。
任何提議的解決方案,或者您可以為母公司設想的任何解決方案,都會遇到同樣的問題:圍繞模式修改鎖合併點。
無論您是執行截斷,還是更改表 …switch,或 sp_rename,更改模式,都無所謂。它們都是變相的相同解決方案。當被截斷/切換/重命名/轉移的表必須使用 SCH-M 鎖定時,所有這些都會有一個時間點。理論上,這是一個“僅瞬時元數據操作”,但實際上在釋放表上所有其他現有鎖之前,無法授予 SCH-M,這意味著已經在表上執行的任何查詢都必須先完成。好的,該操作將等到現有查詢“耗盡”。問題是沒有其他查詢可以進入直到未決的 SCH-M 被授予和釋放。這是一個眾所周知的鎖飢餓問題緩解措施。因此,突然之間,您的所有新查詢都會凍結,直到最後一個舊查詢完成,然後發生截斷/切換/傳輸,新查詢最終恢復。如果所有查詢都持續 1 秒,這並不明顯,但如果查詢是平均持續幾分鐘的報告/分析,則效果非常明顯,特別是如果您的尾巴很長。
好消息是你可以不用擔心如何去做你想做的事:這是不可能的。壞消息是您現在必須修復應用程序。
離開 Martin 的評論,您可以擁有該表的第二個副本作為影子。首先創建兩個模式以方便循環:
CREATE SCHEMA fake AUTHORIZATION dbo; CREATE SCHEMA shadow AUTHORIZATION dbo;
現在在影子模式中創建一個相同的表,您目前正在截斷並重新填充:
CREATE TABLE shadow.whatever(cols); -- add PK, indexes etc.
然後更改您的流程,以便在使用者查詢主節點時,它:
- 清空副本
- 填充空副本
- 交換主要和副本
範常式式碼:
TRUNCATE TABLE shadow.whatever; INSERT shadow.whatever([cols]) SELECT [cols] FROM [source]; BEGIN TRANSACTION; ALTER SCHEMA fake TRANSFER dbo.whatever; ALTER SCHEMA dbo TRANSFER shadow.whatever; COMMIT TRANSACTION; ALTER SCHEMA shadow TRANSFER fake.whatever;
這實質上是在使用者眼皮子底下換了表,但它是瞬時的
ALTER TABLE / SWITCH
,它只是元數據更改,所以事務將等到輪到它並在幾微秒內完成,不會造成任何可見的阻塞(只要因為您的使用者都沒有執行需要將架構更改為whatever
.我們在我之前的工作中做過類似的事情,我在這篇博文中詳細介紹了:
http://www.sqlperformance.com/2012/08/t-sql-queries/t-sql-tuesday-schema-switch-a-roo
考慮到 Remus 的觀察,並假設您的報告查詢確實需要很長時間,並且您可以通過儲存過程強制執行數據訪問,您可以通過保留兩個數據副本並在目前“計劃中的活動”表,該計劃比最長查詢通常花費的時間要長一些。當您填充備份副本時,應該完成對目前副本的所有查詢。當備份副本完成時,您在表中進行標記,並且儲存過程會檢查該表以確定它將使用哪個副本。這將減少(但不能完全消除)圍繞
Sch-M
鎖,當然是以儲存數據的多個副本和稍微複雜的過程為代價的。你會認為統計數據和計劃會走向地獄,但在你目前的方法和我上面建議的更簡單的方法中已經是這種情況。