27,580
社区成员




CREATE PROCEDURE [dbo].[Pro_IndexDefrag]
@DbName Varchar(50), --数据库名
@Mode Varchar(10), --扫描模式
--LIMITED:模式运行最快,扫描的页数最少。对于堆,它将扫描所有页,但对于索引,则只扫描叶级上面的父级别页。
--SAMPLED:模式将返回基于索引或堆中所有页的 1% 样本的统计信息。如果索引或堆少于 10,000 页,则使用DETAILED模式代替 SAMPLED。
--DETAILED:模式将扫描所有页并返回所有统计信息。
@avg_fragmentation_in_percent Decimal, --碎片百分比检测最小值
@RebuildPercent Decimal --重建索引的碎片百分比最小值
AS
BEGIN
SET NOCOUNT ON;
Declare @Sql Varchar(max),@TableName Varchar(50),@SchemaName Varchar(50),@IndexName Varchar(50),@FragmentPercent Decimal
If Exists(Select * From sys.objects Where OBJECT_ID=OBJECT_ID('##Temp_IndexDefrag'))
Drop Table ##Temp_IndexDefrag
--获取非小表(页数>8)碎片百分比超过@avg_fragmentation_in_percent的索引及相关信息
Set @Sql='Select t.Name As TableName '+
',sc.Name As SchemaName '+
',i.name As IndexName '+
',s.avg_fragmentation_in_percent As FragmentPercent '+
'Into ##Temp_IndexDefrag '+
'From sys.dm_db_index_physical_stats(DB_ID('''+@DbName+'''),NULL,NULL,'+
'NULL,'''+@Mode+''') AS s '+
'Join sys.indexes i '+
'On s.object_id=i.object_id And s.index_id=i.index_id '+
'Join sys.tables t '+
'On i.object_id=t.object_id '+
'Join sys.schemas sc '+
'On t.schema_id=sc.schema_id '+
'Where s.avg_fragmentation_in_percent>'+Convert(Varchar(10),@avg_fragmentation_in_percent)+
' And t.Type=''U'''+
' And s.page_count>8'
Exec (@Sql)
--利用游标:判断碎片百分比20~40的重新组织索引,超过40的重建索引
Declare cs Cursor For
Select TableName,SchemaName,IndexName,FragmentPercent From ##Temp_IndexDefrag
Open cs
Fetch Next From cs Into @TableName,@SchemaName,@IndexName,@FragmentPercent
While @@FETCH_STATUS=0
Begin
If @FragmentPercent Between @avg_fragmentation_in_percent And @RebuildPercent --碎片比率在XX%~YY%的重新组织
Begin
Set @Sql='Alter Index '+@IndexName+'On '+@DbName+'.'+@SchemaName+'.'+@TableName+'REORGANIZE'
Exec (@Sql)
End
Else ----碎片比率超过YY%的重建
Begin
Set @Sql='Alter Index '+@IndexName+'On '+@DbName+'.'+@SchemaName+'.'+@TableName+'REBUILD'
Exec (@Sql)
End
Fetch Next From cs Into @TableName,@SchemaName,@IndexName,@FragmentPercent
End
Close cs
Deallocate cs
Drop Table ##Temp_IndexDefrag
END
GO