2010-01-15 58 views
5

我正在運行一個存檔腳本,該腳本根據它們輸入的日期從大型(〜50m記錄DB)中刪除行。日期字段是表格中的聚集索引,因此我正在應用我的條件語句。由於索引而導致sql server刪除速度急劇下降

我運行這個刪除while循環,試圖從1000到10萬條記錄在批處理東西。無論批量大小如何,它都令人驚訝地慢;就像10,000條記錄被刪除一分鐘。看看執行計劃,「索引刪除」花費了大量的時間。表格中大約有15個字段,其中大約10個字段具有某種索引。有什麼辦法可以解決這個問題嗎?我甚至不知道爲什麼每次索引刪除需要這麼長時間,有人可以對這裏發生的事情有所瞭解嗎?這是我執行計劃的樣本:

alt text http://img94.imageshack.us/img94/1006/indexdelete.png

(序列點delete命令)

這個數據庫是活的,並且越來越頻繁插入,這就是爲什麼我很猶豫使用修剪大小的複製和截斷方法。我還有其他選擇嗎?

+2

完全有必要擁有所有這些索引嗎?如果你不使用索引,你應該擺脫它們。 – 2010-01-15 19:41:27

+0

我剛剛和我們網站上的主程序員談過了,聽起來好像我們可能不需要所有的人了。雖然我們在表格上進行了一些查詢,但更經常用作日誌類型的表格。我可能會嘗試刪除一些插入,然後再次運行刪除腳本。 – Kevin 2010-01-15 20:17:46

回答

1

更多的解決方法,但是您可以將IsDeleted標誌添加到表中並將其更新爲1而不是刪除行嗎?您將需要修改您的SELECTsUPDATEs以使用此標誌。

然後,您可以安排在非工作時間刪除或存檔這些記錄。

+0

那麼,我打算在每天的下班時間定期運行這個腳本以保持數據庫的不變(它會刪除任何超過2年的記錄),但是最初的運行非常緩慢,需要4小時才能完成,不僅僅是希望服務器綁定的權力。還是)感謝你的建議! – Kevin 2010-01-15 19:43:16

+1

在這種情況下,只需一次刪除較小的批次(例如,1,000),以便從最終用戶的角度對服務器負載沒有可察覺的影響,並在每個循環之間延遲30-60秒重複此操作。然後讓它運行直到完成。可能需要一兩個星期,但應該完成工作。 – RedFilter 2010-01-15 20:02:09

1

這將需要一些工作來實現它給出的這是在生產,但如果你是SQL Server上2008分之2005您應該調查並轉換表被分區,那麼陳舊數據的刪除,可以非常快速地實現。它設計用於「滾動窗口」類型的效果,並防止大規模刪除將表格/過程綁定在一起。

不幸的是隨着產量的表,它遷移到跨越這個技術需要一定的T-SQL編碼,知識和週末升級/遷移它。一旦到位,雖然任何現有的選擇和插入將無縫地對付它,分區維護和添加/刪除是您需要t-sql來控制過程的地方。

2

我第二次提出@NickLarsen在評論中提出的建議。看看你是否有unused indexes並放下它們。這可以減少這些索引刪除的開銷,這可能足以使操作更及時。

另一個更激進的策略是放下全部索引,執行刪除操作,然後快速重新創建現在較小的數據集的索引。這並不一定會中斷服務,但同時它可能會讓查詢慢很多。雖然我不是Microsoft SQL Server專家,但您應該就此策略提出一些建議。

3

假設表中的每條記錄有5條索引記錄。

現在每個刪除本質上是5個操作。

除此之外,你有一個聚集索引。注意聚集索引刪除時間很長? (10倍)比其他指標長?這是因爲您的數據正在被刪除的每個記錄重新組織。

我會建議刪除至少該索引,做一個大規模刪除,比重新申請。刪除和插入的索引操作固有成本高昂。單個重建可能會快很多。

6

從聚簇索引中刪除10k記錄+ 5個非聚簇記錄應該定義爲不需要1分鐘。聽起來就像你有一個非常慢的IO子系統。什麼是價值觀:

  • 平均。磁盤sec /寫入
  • 平均磁盤秒/讀取
  • 平均。磁盤寫入隊列長度
  • 平均磁盤讀隊列長度

在操作涉及的每個驅動器(包括Log的!)。如果將索引放置在單獨的文件組中,並將每個文件組分配給自己的LUN或自己的磁盤,則可以確定哪些索引更成問題。另外,日誌刷新可能是一個主要瓶頸。 SQL Server在這裏沒有太多的控制權,掌握在你自己的手中如何加快速度。該時間不用於CPU週期,等待IO完成,您需要爲您需要的負載校準的IO子系統。

爲了減少IO負載,您應該考慮縮小索引。首先,確保聚集索引是可行的最窄的。然後,確保非聚簇索引不包括未被使用的大型列(我見過......)。啓用page compression可能會帶來巨大收益。最終,檢查sys.dm_db_index_usage_stats中的索引使用情況統計信息,並查看是否有任何索引適合斧頭。

如果你不能減少IO負載,你應該嘗試分割它。將文件組添加到數據庫,將大型索引移動到單獨的文件組上,將文件組放置在單獨的IO路徑(不同的主軸)上。

對於未來的常規刪除操作,最好的選擇是使用分區切換,使所有索引與聚簇索引分區對齊,並在時間到期時,放下最後一個分區以進行閃電刪除。

+0

我相當有信心硬件超過能力。我們有單獨的英特爾SSD用於日誌和數據,另一個用於操作系統。它具有雙至強四核處理器和16Gb DDR3內存。 我們結束了這個週末的行程,清理了約25米的行。現在我們每晚都要運行它以保持數據庫的清潔和乾淨,而且只需要一兩分鐘。 – Kevin 2010-01-18 15:16:46

+8

你很有自信,你甚至不會去衡量? – 2010-01-18 18:22:36

相關問題