最近有一張表(內含varchar(max)字段),占用空間達到240G,刪除歷史數據后幾十萬條后,空間并未得到釋放。
然后用DBCC CLEANTABLE(0,tb_name,100)來釋放刪除記錄后變長字段留下的空間,注意第三個參數為每個事務處理的行數,
強烈建議使用,默認是0,將整個操作作為一個事務處理!全程鎖表!!
執行完DBCC CLEANTABLE后,發現表空間已經釋放,占用空間幾百兆,但此時還沒完,我們數據庫文件依然很大。
于是我們嘗試用DBCC SHRINKFILE來收縮庫文件,結果卻出人意料,文件并沒有收縮到我們預想的大小,而是遠遠大于所有表
的大小之和,100G之多,為什么?
我們通過DBCC SHOWFILESTATUS命令查看分區狀態,發現有大量的未使用分區,于是開始懷疑是區內頁填充密度過低導致的,
每個區8個頁,如果有一個頁不為空,SHRINKFILE命令也不會收縮該分區,因為SHRINKFILE命令是以區為單位的,它只會收縮掉
完全空的分區。
所以下面我們來看一下“肇事”表的填充密度到底如何,這里我們使用DBCC SHOWCONFIG(‘TB’)命令:
可以看到,雖然這張表的區的利用率比較低,為25.76%[34:132],即本來用34個分區就可以容納的數據,它用了132個分區來容納,
但是遠遠不可能造成上面199萬個區的空間耗費!這到底是怎么回事!!
沒錯,bug再一次顯了神威!相關KB:http://support.microsoft.com/kb/2967240/en-us
那么還有沒有其它方法呢?答案是肯定的,那就是重建該對象:
方法1:重新一張結構一樣的表,將原表數據導入新表,干掉原表,重命名新表;
方法2:將現有數據導出,TRUNCATE表,然后再將數據導回;
另外,經過測試,上面KB中提出的CU13 FOR SQL SERVER 2008 R2 SP2,安裝之后并不能使DBCC SHRINKFILE生效,故應該為避免以上情景的出現!
文章列表