【數據庫】記一次DELETE九千萬條數據的經歷

週四晚上要把測試數據庫結構備份一份週五到客戶方部署到客戶的測試服務器上。

之前備份一個庫一般幾分鐘十幾分鍾吧,⏰18點下班的我決定17點停掉測試站點開始備份數據,嘻嘻~

二十分鐘後數據備份完成,看了下文件大小20G,俺擦怎麼拷到客戶機,而且也不應該有這麼大的數據,於是開始下面的表演~

1.查看庫中每個表的數據量

SELECT  a.name AS 表名 ,
        MAX(b.rows) AS 記錄條數
FROM    sys.sysobjects AS a
        INNER JOIN sys.sysindexes AS b ON a.id = b.id
WHERE   ( a.xtype = 'u' )
GROUP BY a.name
ORDER BY 記錄條數 DESC

發現有張表有九千五百萬數據

看看這張表裏都是什麼數據:SELECT TOP 100 * FROM RoomStatus_Dump

啊~難受😭 。一個SELECT執行了3分鐘。

檢查發現有2011年的數據,只有6千條2019年的數據是需要的,2019年以前的數據全刪掉吧😡

使用truncate大概1秒就搞定了,好嗨喲~使用delete,但在刪除時我可以根據條件時間小於2019年嗎?(上面查詢100條用了三分鐘)

於是決定時間倒敘查詢後按月刪吧,刪了幾次後總結出來規律,每刪除1千萬數據(6個月數據量)大概需要十分鐘

算了一下:(2019-2011)* 2 * 10=160分鐘;去領個盒飯吧~🍗

我覺得可能這張表的索引碎片膨脹了

 

2.檢查表中的索引碎片

--檢查表的索引碎片情況
DECLARE @table_id INT;
SET @table_id = OBJECT_ID('RoomStatus_Dump');
--執行
DBCC SHOWCONTIG(@table_id);

解釋如下:

Page Scanned-掃描頁數

如果你知道行的近似尺寸和表或索引裏的行數,那麼你可以估計出索引裏的頁數。看看掃描頁數,如果明顯比你估計的頁數要高,說明存在內部碎片。 

Extents Scanned-掃描擴展盤區數

用掃描頁數除以8,四捨五入到下一個最高值。該值應該和DBCC SHOWCONTIG返回的掃描擴展盤區數一致。如果DBCC SHOWCONTIG返回的數高,說明存在外部碎片。碎片的嚴重程度依賴於剛纔顯示的值比估計值高多少。 

Extent Switches-擴展盤區開關數

該數應該等於掃描擴展盤區數減1。高了則說明有外部碎片。 

Avg. Pages per Extent-每個擴展盤區上的平均頁數

該數是掃描頁數除以掃描擴展盤區數,一般是8。小於8說明有外部碎片。 

Scan Density [Best Count:Actual Count]-掃描密度[最佳值:實際值]

DBCC SHOWCONTIG返回最有用的一個百分比。這是擴展盤區的最佳值和實際值的比率。該百分比應該儘可能靠近100%。低了則說明有外部碎片。

Logical Scan Fragmentation-邏輯掃描碎片

無序頁的百分比。該百分比應該在0%到10%之間,高了則說明有外部碎片。 

Extent Scan Fragmentation-擴展盤區掃描碎片

無序擴展盤區在掃描索引葉級頁中所佔的百分比。該百分比應該是0%,高了則說明有外部碎片。 

Avg. Bytes Free per Page-每頁上的平均可用字節數

所掃描的頁上的平均可用字節數。越高說明有內部碎片,不過在你用這個數字決定是否有內部碎片之前,應該考慮fill factor(填充因子)。 

Avg. Page Density (full)-平均頁密度(完整)

每頁上的平均可用字節數的百分比的相反數。低的百分比說明有內部碎片

 

3.清除索引碎片

有很多方法,我這裏使用刪除重建索引🤺

--刪除索引
DROP INDEX RoomStatus_Dump.idx_RoomStatus_Dump_hotelid
DROP INDEX RoomStatus_Dump.PK_RoomStatus_Dump

--聚集索引
create CLUSTERED INDEX PK_RoomStatus_Dump ON RoomStatus_Dump(字段, 字段, 字段)
--創建非聚集索引
create NONCLUSTERED INDEX idx_RoomStatus_Dump_hotelid ON  RoomStatus_Dump(字段)

再來看下索引碎片情況,完美~👏

 

4.報錯了“數據庫事務日誌已滿”

 

DELETE是DML,執行DELETE操作時,每次從表中刪除一行,並且同時將該行的的刪除操作記錄在redo和undo表空間中以便進行回滾(rollback)和重做操作,但要注意表空間要足夠大,需要手動提交(commit)操作才能生效,可以通過rollback撤消操作。

好吧刪除日誌,查看日誌存放位置:右鍵數據庫→屬性→文件

 

日誌文件已經80G了😂

 

5.刪除日誌文件

數據庫屬性→選項 恢復模式設置爲簡單

 

 右鍵數據庫→任務→收縮→文件

 

 再檢查下日誌只有幾兆了,刪完記得把恢復模式再改回完整。

 

刪除後備份文件500M,能接受。

⌚19:50

🏍溜了溜了

 

6.彩蛋

將表生成腳本,創建新的表,將6千條需要的數據插入到新表,然後truncate掉舊錶,將新表改名爲舊錶的表名。

十分鐘搞定😝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章