日期:2014-05-17  浏览次数:20615 次

[求助]数据文件收缩不能释放空间
闭门造车,孤陋寡闻,今天手上这个问题实在解决不了,厚颜来求助各位大虾,求指点。

如下:
数据库:SQL SERVER 2005 

问题描述:手上这个系统的数据库,是5年前建立的,设计不合理、维护不规范等等就先不用提了,现在有迫在眉睫的问题是,数据文件太大,无法收缩。

只有一个数据文件primary,日志为简单模式。文件大小:1.48T(你没看错,是T不是G),所在盘1.98T,剩余空间80G

该数据库一直没有做历史数据的常规清理、表索引定期重建等工作。所以到我手上的时候,就是这么大了。前些时候硬盘空间不足报警,我把几个历史大表数据统统删除,尤其其中一个巨大的,占空间900G的数据表,直接迁移至另外的服务器,drop原表后重建。

本拟经过数据库收缩,可以数据文件的剩余空间释放出来给系统,但是执行了一次,成功,但数据文件只小了2G;我重建了所有数据表索引,执行数据文件收缩,成功,但数据文件没变小。又执行一次,还是如此。

有没有高手能给些指点?万分感谢,急!

------解决方案--------------------
试试shrinkfile 
处于使用状态吗?
------解决方案--------------------
DBCC shrinkfile是作用在【区】一级的动作,如果你的空间是在一个区里面,那么是无效的。如果重建聚集索引或者对没有的聚集索引的表创建后收缩还是没效果的话(实际上这步是重组数据,使其尽量集中在区里面,从而释放出空的区用于DBCC shrinkfile)。可以尝试(记得做好备份)以下方法:方法来源于《SQLServer2008企业级平台管理》
1、找到特别大的几个表。把数据导入到别的表,然后truncate,而不是delete,然后把数据插回来,然后创建聚集索引,这样是为了处理原表的碎片。
2、利用DBCC EXTENTINFO命令打开数据文件里面的所有区的分配信息。然后计算每个对象理论上区的数目和实际的数据,如果实际数目远大于理论的数目,证明碎片过多。就要考虑重建对象。参考代码:
SQL code
CREATE TABLE extentinfo
 (
 [FILE_ID] SMALLINT,
 page_id INT,
 pg_alloc INT,
 ext_size INT,
 obj_id INT ,
 index_id INT,
 partition_number INT ,
 partition_id BIGINT,
 iam_chain_type VARCHAR(50),
 pfs_bytes VARBINARY(10)
 )
 go
 
 CREATE PROC import_extentinfo AS 
 DBCC extentinfo('AdventureWorks')
 GO
 INSERT INTO extentinfo
 EXEC import_extentinfo
 GO
 SELECT [file_id],obj_id,index_id,PARTITION_id,ext_size,'actual extent count'=COUNT(*),
 'actual page count'=SUM(pg_alloc),'possible extent count'=CEILING(SUM(pg_alloc)*1.0/ext_size),
 'possible extents /actual extents'=(CEILING(SUM(pg_alloc)*1.00/ext_size)*100.00)/COUNT(*)
 FROM extentinfo
 GROUP BY [file_id],obj_id,index_id,PARTITION_id,ext_size
 HAVING COUNT(*)-CEILING(SUM(pg_alloc)*1.0/ext_size)>0
 ORDER BY PARTITION_id,obj_id,index_id,[file_id]