本文描述了如何识别那些内部(在数据页内部)或者外部(在数据页外部)产生碎片的表。
对一个大数据库执行dbcc re-index的过程是一项很消耗时间的任务。大多数情况下,碎片只是发生在数据库的一部分,并且集中在少数几个表中。应该对这些表进行充分地重建索引,这样宝贵的时间和计算机资源就会被节省下来。
这里我描述一下识别产生碎片的表的方法。我使用dbcc showcontig t-sql语句作为基本语句,来收集使用了群集索引(clustered index)的数据库中所有的用户表信息。在这里,假设群集索引中的碎片会导致所有其他索引中产生碎片,因为群集索引(cluster index)被作为“群集关键字(cluster key)”与所有其他的在其上构造的非群集索引(non-clustered index)一起使用。
我使用带有tablesresult子句的dbcc showcontig语句来查询产生的结果表,以列出所有包含内部碎片或者外部碎片的表的名字,其中内部碎片低于一个给定的可接受的扫描密度百分比,外部碎片大于一个给定的外部碎片百分比。产生的表应该用re-index 或 index defrag进行碎片整理。
下面是识别包含碎片的表的程序代码。这个程序需在数据库中编译,以便进行重建索引。
create procedure sp_list_fragmented_tables
( @internalfragmentationpctallowed int,
@externalfragmentationpctallowed int )
as
begin
declare @showcontigstmt varchar(100)
declare @currtable varchar(50)
/*定义有一个集群索引的user表的指针*/
declare c_examined_tables
cursor for select a.table_name from
information_schema.tables a,sysindexes b
where a.table_type = ''base table'' and
a.table_name = object_name (b.id) and
b.indid = 1
set nocount on
/* 生成作为临时图表的结果图表*/
create table #showcontigresults
(objectname sysname,
objectid bigint,
indexname sysname,
indexid int,
[level] int,
pages int ,
[rows] bigint,
minrecsize int,
maxrecsize int,
avgrecsize real ,
forwardrecs int,
extents int,
extentswitches int,
avgfreebytes real,
avgpagedensity real,
scandensity decimal(5,2),
bestcount int,
actcount int,
logicalfrag decimal (5,2),
extentfragmentation decimal (5,2))
/* 循环所有的图表并执行以tableresults格式的dbcc showcontig 语句 */
open c_examined_tables
fetch next from c_examined_tables into @currtable
while @@fetch_status = 0
begin
set @showcontigstmt = ''dbcc showcontig (['' + @currtable + ''])'' +
'' with tableresults''
insert #showcontigresults exec (@showcontigstmt)
fetch next from c_examined_tables into @currtable
end
close c_examined_tables
deallocate c_examined_tables
/* 输出符号条件的碎片对象*/
select objectname , scandensity , extentfragmentation
from #showcontigresults
where scandensity < @internalfragmentationpctallowed or
extentfragmentation > @externalfragmentationpctallowed
end
go
下面是调用函数的例子:
/* 列出少于50% scan密度的 (内部碎片) 和超过10% 外部碎片图表 */
exec sp_list_fragmented_tables 50,10
我在这里展示的过程可作为工具来识别包含碎片的表,并且将碎片整理或重建索引的维护任务集中在这些对象上,这样就可以减少大数据库中那些占用大量时间和资源的,对所有表进行重建索引的作业。