SQL Server dbcc shrinkfile 不起作用
2014-09-27 08:41
344 查看
方法 1、重建聚集索引。
方法 2、重建堆表。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
原理说明。dbcc shrinkfile 的操作单位是区(extent 也有的书上说成是扩展),数据存在数据页中,8 个数据页的集合叫做一个区(extent)。
区有统一区和混合区之分。如果一个对象所占的空间大于 8 个页面(一个页面在大小是8KB,所以说一个区的大小是64KB)对象的空间分配都
要以区为单位(就是说每一次分配最少给它64KB),如果对象小于64KB,每次的空间分配都以页为单位(就是说一次给它 8KB的空间)。
例子、
create table T(X int ,String nvarchar(4000));
go -- 这个表的第一行都接近8KB 所以一个页面只可以存一行。
declare @i as int =1;
while @i <=1000
begin
insert into T(X,String) values
(1,replicate(N'A',4000)),
(2,replicate(N'A',4000)),
(3,replicate(N'A',4000)),
(4,replicate(N'A',4000)),
(5,replicate(N'A',4000)),
(6,replicate(N'A',4000)),
(7,replicate(N'A',4000)),
(8,replicate(N'A',4000));
set @i = @i +1;
end
go -- 向表中插入8000行数据。
数据的页面如下、
dbcc showcontig('T');
![](http://images.cnitblog.com/blog/643807/201409/262328428736057.jpg)
可以看到T这个表有8000面
这时我们来做一件事,就是用delete 命令删除表中数据的 7/8;代码如下。
delete from T
where T.X != 1;
这样就只留下了X = 1 的行。它要占的空间是1000个页面、可是事实真的是主样吗?我们用dbcc showcontig('T')看一下
dbcc showcontig('T');
![](http://images.cnitblog.com/blog/643807/201409/262336127797804.jpg)
可以看到它还是占着4124个页面不是我们想的1000个页面。因为表T是一个堆表,它内部的数据是无序的也就是说不是 1、2、3、4、5、6、7、8
这种方式存的。内部的区可能是这样的
![](http://images.cnitblog.com/blog/643807/201409/262351173427021.jpg)
话说回来,如果表T 它是有序的呢? 前1000个页面存的会是 1、也就是说后面的7000个页面不会出现1。堆表是无序的每个页面都可能
出现 1。
重点:
问题的重点来了,dbcc shrinkfile 的操作对象是区、也就是说只有空的区才可以被shrinkfile回收、刚才的dbcc shrinkfile('T') 的返回可以看出有4124个页面
存在,说明500(4123/8)多个区中保存着 1 的数据、所以它没有被回收。如果聚集表后面7000个页面所在的区都会被回收。因为这些区都是空的。
--------------------------------------------------------------------------------------------------------------------------------------------------------------
方法 1、:
重建堆表。
alter table T rebuild;
go
![](http://images.cnitblog.com/blog/643807/201409/270826304823426.jpg)
可以看到页面的占用由4123页变回了1001页。
方法 2、
加聚集索引
create clustered index idx_X
on T(X);
go
![](http://images.cnitblog.com/blog/643807/201409/270833216707946.jpg)
可以看到加聚集索引也可以达到一样的效果。
总结:DBA 要定期对表进行管理以减少它的碎片化程度,减少select 时的IO量,提高select 的速度。事实上聚集索引对insert 可以说基本上没有太
大的影响。对select ,update ,delete 的好处是大大的。本例可以看到它对空间的占用也是有利的。
所以、对表加一个聚集索引还是相当不错的。
方法 2、重建堆表。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
原理说明。dbcc shrinkfile 的操作单位是区(extent 也有的书上说成是扩展),数据存在数据页中,8 个数据页的集合叫做一个区(extent)。
区有统一区和混合区之分。如果一个对象所占的空间大于 8 个页面(一个页面在大小是8KB,所以说一个区的大小是64KB)对象的空间分配都
要以区为单位(就是说每一次分配最少给它64KB),如果对象小于64KB,每次的空间分配都以页为单位(就是说一次给它 8KB的空间)。
例子、
create table T(X int ,String nvarchar(4000));
go -- 这个表的第一行都接近8KB 所以一个页面只可以存一行。
declare @i as int =1;
while @i <=1000
begin
insert into T(X,String) values
(1,replicate(N'A',4000)),
(2,replicate(N'A',4000)),
(3,replicate(N'A',4000)),
(4,replicate(N'A',4000)),
(5,replicate(N'A',4000)),
(6,replicate(N'A',4000)),
(7,replicate(N'A',4000)),
(8,replicate(N'A',4000));
set @i = @i +1;
end
go -- 向表中插入8000行数据。
数据的页面如下、
dbcc showcontig('T');
![](http://images.cnitblog.com/blog/643807/201409/262328428736057.jpg)
可以看到T这个表有8000面
这时我们来做一件事,就是用delete 命令删除表中数据的 7/8;代码如下。
delete from T
where T.X != 1;
这样就只留下了X = 1 的行。它要占的空间是1000个页面、可是事实真的是主样吗?我们用dbcc showcontig('T')看一下
dbcc showcontig('T');
![](http://images.cnitblog.com/blog/643807/201409/262336127797804.jpg)
可以看到它还是占着4124个页面不是我们想的1000个页面。因为表T是一个堆表,它内部的数据是无序的也就是说不是 1、2、3、4、5、6、7、8
这种方式存的。内部的区可能是这样的
![](http://images.cnitblog.com/blog/643807/201409/262351173427021.jpg)
话说回来,如果表T 它是有序的呢? 前1000个页面存的会是 1、也就是说后面的7000个页面不会出现1。堆表是无序的每个页面都可能
出现 1。
重点:
问题的重点来了,dbcc shrinkfile 的操作对象是区、也就是说只有空的区才可以被shrinkfile回收、刚才的dbcc shrinkfile('T') 的返回可以看出有4124个页面
存在,说明500(4123/8)多个区中保存着 1 的数据、所以它没有被回收。如果聚集表后面7000个页面所在的区都会被回收。因为这些区都是空的。
--------------------------------------------------------------------------------------------------------------------------------------------------------------
方法 1、:
重建堆表。
alter table T rebuild;
go
![](http://images.cnitblog.com/blog/643807/201409/270826304823426.jpg)
可以看到页面的占用由4123页变回了1001页。
方法 2、
加聚集索引
create clustered index idx_X
on T(X);
go
![](http://images.cnitblog.com/blog/643807/201409/270833216707946.jpg)
可以看到加聚集索引也可以达到一样的效果。
总结:DBA 要定期对表进行管理以减少它的碎片化程度,减少select 时的IO量,提高select 的速度。事实上聚集索引对insert 可以说基本上没有太
大的影响。对select ,update ,delete 的好处是大大的。本例可以看到它对空间的占用也是有利的。
所以、对表加一个聚集索引还是相当不错的。
相关文章推荐
- SqlServerDBCC SHRINKFILE不起作用
- DBCC大全集之(适用版本MS SQLServer 2008 R2)----DBCC SHRINKFILE收缩当前数据库的指定数据或日志文件的大小
- DBCC大全集之(适用版本MS SQLServer 2008 R2)----DBCC CHECKFILEGROUP检查当前数据库中指定文件组中的所有表和索引视图的分配和结构完整性
- Shrink or truncate SQL Server log file
- DBCC大全集之(适用版本MS SQLServer 2008 R2)----DBCC SHRINKDATABASE收缩指定数据库中的数据文件和日志文件的大小
- DBCC SHRINKFILE (Transact-SQL)
- DBCC大全集之(适用版本MS SQLServer 2008 R2)----DBCC CHECKFILEGROUP检查当前数据库中指定文件组中的所有表和索引视图的分配和结构完整性
- DBCC大全集之(适用版本MS SQLServer 2008 R2)---DBCC CHECKFILEGROUP检查当前数据库中指定文件组中的所有表和索引视图的分配和结构完整性
- 如何解决DBCC SHRINKFILE命令不起作用
- DBCC大全集之(适用版本MS SQLServer 2008 R2)----DBCC CHECKFILEGROUP检查当前数据库中指定文件组中的所有表和索引视图的分配和结构完整性
- DBCC大全集之(适用版本MS SQLServer 2008 R2)---DBCC CHECKFILEGROUP检查当前数据库中指定文件组中的所有表和索引视图的分配和结构完整性
- 如何在 SQL Server 2005 中使用 DBCC SHRINKFILE 语句收缩事务日志文件-数据库知识
- Exception from HRESULT: 0x800736B1,Could not load file or assembly 'Microsoft.SqlServer.BatchParser
- SQL SERVER DBCC命令解释
- SQL SERVER DBCC命令解释
- 在SQL Server 2005 中使用 DBCC SHRINKFILE 语句收缩事务日志文件
- FILESTREAM Configuration and Setup Changes in SQL Server 2008 February CTP
- SQL SERVER DBCC命令解释
- SQL Server Backup file in standard Zip format
- 每小时自动生成一个SQL Server Profiler文件(Auto Generate an Hourly SQL Server Profiler Trace File)