博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQL Server dbcc shrinkfile 不起作用
阅读量:5837 次
发布时间:2019-06-18

本文共 1810 字,大约阅读时间需要 6 分钟。

方法 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');

            

           可以看到T这个表有8000面

     这时我们来做一件事,就是用delete 命令删除表中数据的 7/8;代码如下。

     delete from T 

     where T.X != 1; 

     这样就只留下了X = 1 的行。它要占的空间是1000个页面、可是事实真的是主样吗?我们用dbcc showcontig('T')看一下

     dbcc showcontig('T');

            

     可以看到它还是占着4124个页面不是我们想的1000个页面。因为表T是一个堆表,它内部的数据是无序的也就是说不是 1、2、3、4、5、6、7、8

     这种方式存的。内部的区可能是这样的

     话说回来,如果表T 它是有序的呢? 前1000个页面存的会是 1、也就是说后面的7000个页面不会出现1。堆表是无序的每个页面都可能

     出现 1。

重点:

      问题的重点来了,dbcc shrinkfile 的操作对象是区、也就是说只有空的区才可以被shrinkfile回收、刚才的dbcc shrinkfile('T') 的返回可以看出有4124个页面

      存在,说明500(4123/8)多个区中保存着 1 的数据、所以它没有被回收。如果聚集表后面7000个页面所在的区都会被回收。因为这些区都是空的。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

方法 1、:

         重建堆表。

         alter table T rebuild;

        go

        

        可以看到页面的占用由4123页变回了1001页。

方法 2、

       加聚集索引      

      create clustered index idx_X

      on T(X);
      go

          

     可以看到加聚集索引也可以达到一样的效果。

总结:DBA 要定期对表进行管理以减少它的碎片化程度,减少select 时的IO量,提高select 的速度。事实上聚集索引对insert 可以说基本上没有太

        大的影响。对select ,update ,delete 的好处是大大的。本例可以看到它对空间的占用也是有利的。

        所以、对表加一个聚集索引还是相当不错的。

 

 

 

 

     

 

转载地址:http://leccx.baihongyu.com/

你可能感兴趣的文章
跟随我在oracle学习php(8)
查看>>
FZU - 1688 Binary land
查看>>
Spring 3.1.0 Hibernate 3.0 Eclipse Spring WEB例子
查看>>
转换流,Properties 集合
查看>>
bootstrap列排序
查看>>
redis 常用操作
查看>>
如何用ABP框架快速完成项目(9) - 用ABP一个人快速完成项目(5) - 不要执着于设计模式和DDD理论,避免原教旨主义...
查看>>
用户交互
查看>>
【ubuntu 修改root密码】
查看>>
libkyototycoon.so.2: cannot open shared object file: No such file
查看>>
ASP.Net 后台发回错误
查看>>
【微服务架构与实践】读后感
查看>>
使用Unicode写文本文件:一个简单类的示例
查看>>
阶乘素因子分解
查看>>
UVA-10212 The Last Non-zero Digit. 分解质因子+容斥定理
查看>>
80端口被占用时的终极解决方法
查看>>
NG-ZORRO 使用相关
查看>>
[algothrim] url pattern mining within same domain site
查看>>
[hihoCoder]HIHO Drinking Game
查看>>
Python变量与赋值
查看>>