SQL Server 大数据空间管理——数据库数据文件循环收缩

最近在进行数据归档整理,整理完后,需要对数据库进行收缩,释放未使用空间。为方便后期重复使用,将相关脚本进行整理。同时也将之分享给业界朋友,希望在您的管理中给予一些提示或者帮助。写到这里也让我回想起第一次收缩一个数据库时候的糗事,收缩两天没有完成,回滚一天还没有结束,最后直接用爆了所有存储^^。每天积累一点,每天进步一点。

本文没有使用 DBCC SHRINKDATABASE 进行数据库收缩,而DBCC SHRINKDATABASE 本质上也是对各个文件(包括数据文件、和日志文件)同时进行收缩,使用其进行数据库收缩,但不容易控制收缩的文件(由其自身控制,无法人为干预)。本人选择使用更容易人为干预控制的 DBCC SHRINKFILE 循环对数据文件进行收缩。为了方便,首先将循环收缩的一个数据文件的脚本封装为一个系统过程,以方便各个库调用,具体脚本如下:

use master
go
/*
	循环收缩数据库的一个数据文件
*/
create proc sp_DBA_ShrinkFile
	@fileName varchar(256)
	,@space int
	,@usedSpace int
	,@shrinkSpace int=10000	--默认每次收缩10GB
as
begin
	while @space>@usedSpace
	begin
		DBCC SHRINKFILE (@fileName , @space)
		set @space=@space-@shrinkSpace	
	end
end

go

脚本每次将文件收缩到一个指定值,循环直至数据文件分配的大小和使用的大小一致时结束。

下面使用 DBCC showfilestats 获取每个数据文件的分配总空间和使用空间,这里返回的是每个数据文件的总 Extent 和 使用的 Extent,SQL Server 中 最小的存储单位是页,一页为8KB,连续的8页称为一个 Extent。

循环数据库中的所有数据文件,调用上面的 sp_DBA_ShrinkFile,对数据库中所有数据文件进行收缩,具体脚本如下:

/************************************************************
	***注意:
	在进行文件收缩时,如果收缩导致死锁,将会导致日志文件迅速增长,注意观察文件大小变化情况,及死锁情况
************************************************************/
use DBA_Monitor

declare @fileName varchar(256)
declare @space int	--第一次收缩后的空间(MB),第一次收缩的空间建议1~2GB
declare @usedSpace int
if OBJECT_ID('tempdb..#dbInfo') is not null
	drop table #dbInfo
create table #dbInfo(Fileid smallint
,FileGroup smallint
,TotalExtents int
,UsedExtents int
,name varchar(256)
,FileName varchar(520)
)

insert into #dbInfo
exec('dbcc showfilestats')

update #dbInfo set TotalExtents=TotalExtents*8*8/1024-1000,UsedExtents=UsedExtents*8*8/1024

declare cur cursor for select name,TotalExtents,UsedExtents from #dbInfo
open cur
fetch next from cur into @fileName,@space,@usedSpace
--set @space=@space*8*8/1024-1000
--set @usedSpace=@usedSpace*8*8/1024
while @@FETCH_STATUS=0
begin
	exec sp_DBA_ShrinkFile @fileName,@space,@usedSpace
	fetch next from cur into @fileName,@space,@usedSpace
	--set @space=@space*8*8/1024-1000
	--set @usedSpace=@usedSpace*8*8/1024
end
close cur
deallocate cur
drop table #dbInfo

注意:在进行数据库数据文件收缩时,要严密关注死锁、日志文件的变化及存储空间的变化。因为一旦收缩文件导致死锁,将会导致日志迅猛增长,从而导致空间急剧减少。

使用这个循环文件收缩脚本收缩一个近2T的数据文件,用了不到1个小时的时间,释放近40%的空间,效率还是蛮可以的,同时想要停止收缩,几乎可以秒停。对于有许多分区文件、大量数据库(听说有人需要管理数百个数据库)的收缩更是一大福音,几乎可以一键搞定(在SSMS中F5运行脚本)。

如果喜欢,可以搜索注公众 MSQLServer,将有更多精彩。

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