数据表空间的重用(Reusing space in a table)

如果删除掉一些数据行,我是否需要压缩SQL Server数据库? 以便于这些空间可以被重新使用.这是一个很好的问题,切经常被问到,其中涉及到SQL Server数据库对删除的管理以及压缩机制.

1.理解SQL Server怎样自动的重新利用数据表的空间,下面以实例来做简要的说明.

1.1 建立临时测试数据

创建一个测试table: Test,填空1000行数据.

 
 
ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
-- create a test table
CREATE TABLE dbo.Test
(
col1
INT
,col2
CHAR ( 25 )
,col3
VARCHAR ( 4000 )
) ;
-- create some test data
DECLARE @cnt INT ;
SET @cnt = 0 ;
WHILE @cnt < 1000
BEGIN
SELECT
@cnt = @cnt + 1 ;
INSERT
dbo.Test ( col1,col2,col3 )
VALUES (
@cnt
,
' test row # ' + CAST ( @cnt AS VARCHAR ( 10 )) + ' A '
,
REPLICATE ( ' ABCD ' , ROUND ( RAND () * @cnt , 0 ))
) ;
END

 

首先介绍一个DMV:sys.dm_db_index_physical_stats
 
 
有几个重要的栏位:
alloc_unit_type_desc:有效值为:IN_ROW_DATA,LOB_DATA,ROW_OVERFLOW_DATA
page_count:储存数据行的数据页数
avg_page_space_used_in_percent:数据页使用的平均百分比
record_count:总的记录数
根据这个DMV看看测试表Test的查询结果:
 
 

 

 
  
-- DMV SQL
select alloc_unit_type_desc,page_count,avg_page_space_used_in_percent,record_count
from sys.dm_db_index_physical_stats( db_id (), object_id ( ' Test ' ), NULL , NULL , ' Detailed ' )

 结果如下:2010032913283555.png

可以看到1000条数据占用152个数据页,平均每个页空间使用率为84.2%
1.2 删除部分旧数据,再次查看数据空间使用率
删除一半的数据.
 
 
 
  
-- delete the odd rows
DELETE FROM Test WHERE col1 % 2 = 1
-- view the table
SELECT * from Test

 重新运行如上的DMV SQL语句得到:

2010032913372117.png
由此可见,储存500条数据仍然占用152个数据页,平均每个页的数据空间使用率为43.2%(几乎是84.2%的1/2)
1.3 在添加一些新的数据行
 
 
ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
-- add some more test data
DECLARE @cnt INT ;
SET @cnt = 0 ;
WHILE @cnt < 500
BEGIN
SET @cnt = @cnt + 1 ;
INSERT INTO dbo.Test ( col1,col2,col3 ) VALUES (
@cnt , ' test row # ' + CAST ( @cnt AS VARCHAR ( 10 )), REPLICATE ( ' WXYZ ' , ROUND ( RAND () * @cnt , 0 ))) ;
END
添加500条数据后,测试表Test现在有1000条数据, 再次重新运行如上的DMV SQL语句得到:
 
 
 可以看到储存1000条数据依然用到152页,但是每个页的空间使用率从43.2%提高到了65.%,说明SQL Server重用表中多余的空间,而没有增加新的数据页.
 在此请注意用到的测试表是用堆存储结构(没有建立索引),表中数据行没有预先特定的排序.在索引表中也同样适用,SQL Server会很好的重用表中空余的空间(holes).
1.4 CLean Up
 
 
 
  
-- clean up
DROP TABLE dbo.Test ;

2.SQL Server不自动回收空间时

在某种情况下,SQL Server并不会自动的回收已经不用的空间.如果一个表的定义被改变(比如说DROP掉一个或者几个栏位),已经消耗掉的空间并不会被SQL Server立即重用.
下面举例说明:
2.1 建立测试数据
 
 
ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
CREATE TABLE dbo.Test2
(
col1
INT
,col2
CHAR ( 25 )
,col3
VARCHAR ( 4000 )
) ;
-- create some test data
DECLARE @cnt INT ;
SET @cnt = 0 ;
WHILE @cnt < 1000
BEGIN
SET @cnt = @cnt + 1 ;
INSERT INTO dbo.Test2 ( col1,col2,col3) VALUES (
@cnt , ' test row # ' + CAST ( @cnt AS VARCHAR ( 10 )), REPLICATE ( ' A ' , 4000 )) ;
END

 2010032915311731.png

同上一个例子一样运行SQL DMV的查询,针对table:Test2
 
 
 
  
-- SQL DMV
select alloc_unit_type_desc,page_count,avg_page_space_used_in_percent,record_count
from sys.dm_db_index_physical_stats( db_id (), object_id ( ' Test2 ' ), NULL , NULL , ' Detailed ' )
可以看到:
1000行数据占用500个数据页,每个页的空间使用率为99.8%
2.2 DROP掉一个栏位(比如col3)
 
 
 
  
ALTER TABLE dbo.Test2 DROP COLUMN col3 ;

 

运行SQL DMV之后看到的是:
 
 
和DROP掉一个栏位之前一样的是:1000行数据占用500个数据页,每个页的空间使用率为99.8%.SQL Server并没有回收不用的空间,没有从数据页从移除掉那一栏的数据.
SQL Server的做法只是更新系统表中的元数据,在查询时这一列不会作为结果集显示出来,数据所占的空间也不会被释放掉.
2.3 添加数据
 
 
ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
-- insert additional rows
DECLARE @cnt INT ;
SET @cnt = 0 ;
WHILE @cnt < 500
BEGIN
SET @cnt = @cnt + 1 ;
INSERT INTO dbo.Test2 ( col1,col2 ) VALUES (
@cnt , ' test row # ' + CAST ( @cnt AS VARCHAR ( 10 ))) ;
END

 

再次运行SQL DMV查询:
 
 
1500行的数据占用503个数据页,每个页的空间使用率为99.7%,可以看到新增三个数据页.如果空间可以重用的话,应该会有足够多的空间存储新增的500行数据,并不需要新增数据页.

3.空间回收(DBCC CLEANTABLE)

在某些情况下SQL Server会自动的回收空间重复利用,但是在某些情况下则不会.
可以通过DBCC Command来回收不用的空间.
 
 
 
  
DBCC CLEANTABLE( ' TEST ' , ' dbo.Test2 ' ) ;

 

运行过之后可以看到:
 
 
回收不用的空间以后,页面空间使用率大大降低.还是503个页,并没有压缩.
在DROP,DELETE之后用DBCC CLEANTABLE可以及时回收做删除标记的资料作占用的空间,可以更好的提高页面和磁盘的空间利用率.

转载于:https://www.cnblogs.com/changbluesky/archive/2010/03/29/1699549.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值