大致的重建範圍是 邏輯密度碎片>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