SQL Server索引重建和重新组织脚本

    为了有针对性的重建索引,提高数据库的效能,同时避免因全部重建造成服务器的Loading,我们内部有开发一个存储过程脚本,逻辑大概如下:

    首先遍历该实例中所有数据库中所有table中的index,并将Fragment保存到临时表中,这当中用到了一个系统存储过程:sp_MSforeachdb 可以实现对所有数据库的循环遍历;然后对临时表中的数据进行处理,如果

碎片介于20%--40%,则对索引进行重新组织,大于40%则进行重建。

View Code
  1 USE [msdb]
  2 GO
  3 /****** Object:  StoredProcedure [dbo].[IndexMaintain]    Script Date: 09/14/2012 17:59:33 ******/
  4 SET ANSI_NULLS ON
  5 GO
  6 SET QUOTED_IDENTIFIER ON
  7 GO
  8  -- =============================================
  9 -- Author
 10 -- Create date:  2012/01/17
 11 -- Description:    IndexMaintain
 12 -- ==============================================
 13 ALTER  procedure  [dbo].[IndexMaintain]  
 14 as   
 15 SET NOCOUNT on 
 16  
 17 BEGIN TRY 
 18     declare @EXCEPTION VARCHAR(MAX)
 19     declare @MailSubject NVARCHAR(255)
 20     declare @DBName NVARCHAR(255)
 21     declare @TableName NVARCHAR(255)
 22     declare @SchemaName NVARCHAR(255)
 23     declare @IndexName NVARCHAR(255)
 24     declare @avg_fragmentation_in_percent_old DECIMAL(18,3)
 25     declare @avg_page_space_used_in_percent_old DECIMAL(18,3)
 26     declare @avg_fragmentation_in_percent_new DECIMAL(18,3)
 27     declare @avg_page_space_used_in_percent_new DECIMAL(18,3)
 28             
 29     declare @Defrag NVARCHAR(max)
 30     declare @Sql NVARCHAR(max)
 31     declare @ParmDefinition nvarchar(500)
 32     set @EXCEPTION=''
 33     
 34     --删除#Frag
 35     if exists(select *  from sys.objects where object_id=object_id(N'#Frag'))
 36     drop table #Frag 
 37        
 38     --定义临时表#Frag保存index Fragment    
 39     create table #Frag(
 40                  DBname  NVARCHAR(255),
 41                  TableName NVARCHAR(255),
 42                  SchemaName NVARCHAR(255),
 43                  IndexName NVARCHAR(255),
 44                  AvgFragment DECIMAL(18,3),
 45                  avg_page_space_used DECIMAL(18,3)
 46                  )
 47                  
 48     --遍历DB中所有table上的index,并将Fragment保存到临时表#Frag中.
 49     exec sp_MSforeachdb @command1= 'insert into #Frag(DBname, TableName,SchemaName,IndexName,AvgFragment,avg_page_space_used)
 50                                     select ''[?]'' AS DBName, t.Name AS TableName, sc.Name AS SchemaName, i.name AS IndexName, s.avg_fragmentation_in_percent, s.avg_page_space_used_in_percent  
 51                                     from [?].sys.dm_db_index_physical_stats(DB_ID(''?''),NULL,NULL,NULL,''Sampled'') AS s
 52                                     join [?].sys.indexes i on s.Object_Id=i.Object_id and s.Index_id=i.Index_id
 53                                     join [?].sys.tables t on i.Object_id=t.Object_ID 
 54                                     join [?].sys.schemas sc on t.schema_id=sc.SCHEMA_ID
 55                                     where s.avg_fragmentation_in_percent  >20 and t.type=''U'' and s.page_count>8 and i.allow_page_locks=1 and i.allow_row_locks=1 
 56                                     order by  TableName,IndexName '
 57 
 58     --定义CURSOR遍历临时表#Frag,根据Fragment大小采取不同的方案维护index.
 59     declare cList CURSOR for
 60             select *  from #Frag 
 61     open cList 
 62     fetch next from cList into @DBName,@TableName,@SchemaName,@IndexName,@avg_fragmentation_in_percent_old,@avg_page_space_used_in_percent_old
 63     while @@FETCH_STATUS=0
 64     begin 
 65        set @TableName ='['+ @TableName +']'
 66        --Fragment between 20.0 and 40.0 ,使用 Alter INDEX reorganize整理碎片
 67        if @avg_fragmentation_in_percent_old between 20.0 and 40.0 AND @DBName <>'[TOPCOA]' 
 68        begin          
 69          --整理碎片
 70          set @Defrag=N'Alter INDEX   '+''+@IndexName+' on '+@DBName+'.'+@SchemaName+'.'+@TableName+' reorganize'
 71          exec sp_executesql @Defrag
 72                   
 73          --获取index被整理后的碎片比例
 74          set @Sql=N'USE '+@DBName+'; select @avg_fragmentation_in_percent_new_temp=s.avg_fragmentation_in_percent,@avg_page_space_used_in_percent_new_temp= s.avg_page_space_used_in_percent 
 75                     from  '+@DBName+'.sys.indexes i  
 76                     inner join '+@DBName+'.sys.dm_db_index_physical_stats(db_id(replace(replace('''+@DBName+''',''['',''''),'']'','''')), object_id('''+@TableName+''''+'),null,null,''sampled'') as s on   i.index_id=s.index_id  
 77                     where i.object_id=object_id('''+@TableName+''''+')and i.name='''+@IndexName+''''
 78          set @ParmDefinition=N'@avg_fragmentation_in_percent_new_temp  DECIMAL(18,3) output,@avg_page_space_used_in_percent_new_temp DECIMAL(18,3) output'
 79          exec sp_executesql @Sql,@ParmDefinition ,@avg_fragmentation_in_percent_new_temp=@avg_fragmentation_in_percent_new output, @avg_page_space_used_in_percent_new_temp=@avg_page_space_used_in_percent_new output
 80          
 81          --write log
 82          insert [dbo].IndexDefrag values(@DBName,@TableName,@SchemaName,@IndexName,getdate(),@avg_fragmentation_in_percent_old,@avg_page_space_used_in_percent_old,@avg_fragmentation_in_percent_new,@avg_page_space_used_in_percent_new,'0')
 83        end 
 84         --Fragment大于40.0 ,使用 Alter INDEX rebuild整理碎片
 85        else if @avg_fragmentation_in_percent_old >40.0 AND @DBName <>'[TOPCOA]'
 86        begin          
 87          --整理碎片 
 88          set @Defrag=N'Alter INDEX    '+''+@IndexName+' on '+@DBName+'.'+@SchemaName+'.'+@TableName+' rebuild'
 89          exec sp_executesql @Defrag 
 90          
 91          --获取index被整理后的碎片比例
 92          set @Sql=N'USE '+@DBName+';select @avg_fragmentation_in_percent_new_temp=s.avg_fragmentation_in_percent,@avg_page_space_used_in_percent_new_temp= s.avg_page_space_used_in_percent 
 93                     from  '+@DBName+'.sys.indexes i  
 94                     inner join '+@DBName+'.sys.dm_db_index_physical_stats(db_id(replace(replace('''+@DBName+''',''['',''''),'']'','''')), object_id('''+@TableName+''''+'),null,null,''sampled'') as s on   i.index_id=s.index_id  
 95                     where i.object_id=object_id('''+@TableName+''''+')and i.name='''+@IndexName+''''
 96          set @ParmDefinition=N'@avg_fragmentation_in_percent_new_temp  DECIMAL(18,3) output,@avg_page_space_used_in_percent_new_temp DECIMAL(18,3) output'
 97          exec sp_executesql @Sql,@ParmDefinition ,@avg_fragmentation_in_percent_new_temp=@avg_fragmentation_in_percent_new output, @avg_page_space_used_in_percent_new_temp=@avg_page_space_used_in_percent_new output
 98          
 99          --write log
100          insert [dbo].IndexDefrag values(@DBName,@TableName,@SchemaName,@IndexName,getdate(),@avg_fragmentation_in_percent_old,@avg_page_space_used_in_percent_old,@avg_fragmentation_in_percent_new,@avg_page_space_used_in_percent_new,'1')
101         end 
102       fetch next from cList into @DBName,@TableName,@SchemaName,@IndexName,@avg_fragmentation_in_percent_old,@avg_page_space_used_in_percent_old
103     end 
104     close cList 
105     deallocate cList 
106 END TRY
107 BEGIN CATCH
108     SET @EXCEPTION = ERROR_MESSAGE() 
109 END CATCH
110 
111 IF @EXCEPTION<>''
112 BEGIN 
113     SET @MailSubject='[Important]DB Index Maintainence failed from ' + @@SERVERNAME  
114     EXEC msdb.dbo.sp_send_dbmail
115     @profile_name = 'mail',                     
116     @recipients = '[email protected]',
117     @body = @EXCEPTION, 
118     @subject = @MailSubject 
119     
120 END
121  

你可能感兴趣的:(sql,server)