Sqlserver——日常维护——定期重建索引

大致的重建范围是 逻辑密度碎片>30以及页码总数>8以上的数据库索引碎片

直接上代码(附带生成执行完之后生成日志记录表)

SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
 
Create PROCEDURE [dbo].[p_index_rebuild_test]
AS
 
 
 
DECLARE @DatabaseName NVARCHAR(255)--数据库名
DECLARE @SchemaName NVARCHAR(255)--架构名
DECLARE @TableName NVARCHAR(255)--表名
DECLARE @IndexName NVARCHAR(255)--索引名
DECLARE @IndexType NVARCHAR(255)--索引类型
DECLARE @IndexColums NVARCHAR(MAX)--索引列清单
DECLARE @DuringTime INT--重建时间
DECLARE @Before_avg_fragmentation_in_percent DECIMAL(19,8)--重建前的逻辑扫描碎片
DECLARE @After_avg_fragmentation_in_percent DECIMAL(19,8)--重建后的逻辑扫描碎片
 
 
SET XACT_ABORT ON 
SET NOCOUNT ON 
 
-----------定期重建索引执行计划--------
 
BEGIN TRAN
 
----------1、创建记录表,写入本次索引重构的日志
--日志表名
DECLARE @LogTableName NVARCHAR(255)='ReBuildIndexLog_'+CONVERT(VARCHAR(100),GETDATE(),112)
 
DECLARE @sql NVARCHAR(MAX)=''
 
 
 
IF EXISTS(SELECT * FROM sys.objects WHERE object_id=OBJECT_ID(@LogTableName))
BEGIN
 
SET @sql='drop table '+@LogTableName
EXEC (@sql)
 
END
 
SET @sql ='Create Table '+@LogTableName+'
		   (
		   DatabaseName nvarchar(255),
		   SchemaNam nvarchar(255),
		   TableName nvarchar(255),
		   IndexName nvarchar(255),
		   IndexType nvarchar(255),
		   IndexColums nvarchar(255),
		   DuringTime int,
		   Before_avg_fragmentation_in_percent DECIMAL(19,8),
		   After_avg_fragmentation_in_percent DECIMAL(19,8)
		   ) 
		   '
EXEC (@sql);
SELECT @sql
 
---------2、查询逻辑扫描碎片大于30,并且数据页大于8以上的数据表,并插入到临时表中
 
SELECT  database_id,
		object_id,
		index_id,
		index_type_desc,
		IDENTITY(INT,1,1) AS ID,
		partition_number
		INTO #Temp_A
FROM    sys.dm_db_index_physical_stats(DB_ID(DB_NAME()), NULL, NULL, NULL,
                                       'Sampled')
WHERE   avg_fragmentation_in_percent > 30
        AND page_count > 8;
 
 
 
--------3、循环所有的临时表记录
 
DECLARE @i INT =1
DECLARE @q INT =(SELECT MAX(ID) FROM #Temp_A)
DECLARE @Btime DATETIME--开始时间
DECLARE @Etime DATETIME--结束时间
DECLARE @IndexID INT--索引ID
DECLARE @PartitionNum INT --分区编号
WHILE @i<=@q
BEGIN
SELECT  @DatabaseName = d.name ,--数据库名
        @SchemaName = 'dbo' ,--架构名
        @TableName = t.name ,--表名
		@IndexID=a.index_id,--索引ID
        @IndexName = i.name ,--索引名
        @IndexType = a.index_type_desc,--索引类型
		@PartitionNum=a.partition_number,--分区编号
        @IndexColums = ( SELECT c.name + ','
                         FROM   sys.index_columns ic
                                INNER JOIN sys.columns c ON ic.object_id = c.object_id
                                                            AND ic.index_column_id = c.column_id
                         WHERE  ic.object_id = a.object_id
                                AND ic.index_id = a.index_id
                       FOR
                         XML PATH('')
                       )--索引列
FROM    #Temp_A a
        INNER JOIN sys.databases d ON a.database_id = d.database_id
        INNER JOIN sys.tables t ON a.object_id = t.object_id
        INNER JOIN sys.indexes i ON a.object_id = i.object_id
                                    AND a.index_id = i.index_id
		WHERE a.ID=@i
 
SET @Btime=GETDATE()
 
--PRINT '循环:'+CONVERT(NVARCHAR(20),@i)
 
 
SET @Before_avg_fragmentation_in_percent = ( SELECT TOP 1 avg_fragmentation_in_percent
                                             FROM   sys.dm_db_index_physical_stats(DB_ID(@DatabaseName),
                                                              OBJECT_ID(@TableName),
                                                              @IndexID, @PartitionNum,
                                                              'Sampled')
                                           );
SET @sql='alter index '+@IndexName+' on '+@TableName+' REBUILD With(FILLFACTOR=90)'
 
EXEC(@sql);
 
 
SET @After_avg_fragmentation_in_percent = ( SELECT TOP 1 avg_fragmentation_in_percent
                                             FROM   sys.dm_db_index_physical_stats(DB_ID(@DatabaseName),
                                                              OBJECT_ID(@TableName),
                                                              @IndexID, @PartitionNum,
                                                              'Sampled')
                                           );
 
 
SET @Etime=GETDATE()
 
SET @DuringTime=DATEDIFF(MILLISECOND,@Btime,@Etime)
 
 
 
SET @sql='insert into '+@LogTableName+'
		  select '+CHAR(39)+@DatabaseName+CHAR(39)+',
				 '+CHAR(39)+@SchemaName+CHAR(39)+',
				 '+CHAR(39)+@TableName+CHAR(39)+',
				 '+CHAR(39)+@IndexName+CHAR(39)+',
				 '+CHAR(39)+@IndexType+CHAR(39)+',
				 '+CHAR(39)+@IndexColums+CHAR(39)+',
				 '+CHAR(39)+CONVERT(NVARCHAR(255),@DuringTime)+CHAR(39)+',
				 '+CHAR(39)+CONVERT(NVARCHAR(255),@Before_avg_fragmentation_in_percent)+CHAR(39)+',
				 '+CHAR(39)+CONVERT(NVARCHAR(255),@After_avg_fragmentation_in_percent)+CHAR(39)+'
				 '
EXEC(@sql)
 
 
SET @i=@i+1;
END
 
 
 
 
COMMIT TRAN
 
 
 
 
 
 
GO

 来源:https://blog.csdn.net/qq_40205468/article/details/87289730

posted @ 2021-01-28 15:14  振乾  阅读(612)  评论(0编辑  收藏  举报