重建SQLSERVER索引

 

查詢碎片率

SELECT a.index_id ,B.name [IndexName] ,avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats ( DB_ID() , NULL , NULL, NULL, NULL ) AS A
JOIN sys.indexes AS B ON a.object_id = b.object_id AND a.index_id = b.index_id
inner JOIN sys.tables AS C ON a.object_id=C.object_id
inner JOIN sys.schemas AS D ON C.schema_id=D.schema_id
WHERE a.index_id > 0
order by avg_fragmentation_in_percent desc

執行

exec [P_BatchRebuildIndex] @Scheme=null,@TableName=null,@IndexName=null,@FragmentPercent=20

P_BatchRebuildIndex 創建腳本:

/****** Object: StoredProcedure [dbo].[P_BatchRebuildIndex] Script Date: 2022/5/11 14:00:25 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

-- =============================================
-- Create date: <2017-07-01>
-- Description: <批量重建索引>
-- EXEC P_BatchRebuildIndex 'dbo','','',30
-- =============================================
Create proc [dbo].[P_BatchRebuildIndex]
--@DataBase nvarchar(50)=null,--數據庫名稱,必輸項
@Scheme nvarchar(50)=null,--架構名稱
@TableName nvarchar(50)=null, --要重建索引的表名稱,爲空表示所有表
@IndexName nvarchar(200)=null ,--要重建的索引名稱
@FragmentPercent decimal(10,5)=0 --碎片率爲多少以上的需要重建
AS
BEGIN

DECLARE @Sql nvarchar(2000);
DECLARE @RebuildSql nvarchar(2000);
DECLARE @ERROR nvarchar(500);
DECLARE @Tables table(TableName nvarchar(100), Indexid int,IndexName nvarchar(200), FragmentPercent decimal(10,5));

----判斷數據庫是否存在
--IF DB_ID(@DataBase) is null
--BEGIN
-- RAISERROR('數據庫不存在,請輸入正確的數據庫名稱!',16,1);
-- RETURN -1;
--END


--判斷架構是否存在
IF isnull(@Scheme,'')<>'' and SCHEMA_ID(@Scheme) is null
BEGIN
RAISERROR('架構不存在,請輸入正確的架構名稱!',16,1);
RETURN -1;
END


--表存不存在
IF isnull(@TableName,'')<>''
BEGIN
--有架構
IF isnull(@Scheme,'')<>'' and SCHEMA_ID(@Scheme) is null
BEGIN
IF OBJECT_ID(@Scheme+'.'+@TableName) is null
BEGIN
SET @ERROR='表不存在,請輸入正確的表名稱!'
RAISERROR(@ERROR,16,2);
RETURN -1;
END
END
--沒有架構
IF not exists(select 1 from sys.tables as A where A.name=@TableName )
BEGIN
SET @ERROR='表不存在,請輸入正確的表名稱!'
RAISERROR(@ERROR,16,5);
RETURN -1;
END
END

--索引存不存在
IF isnull(@IndexName,'')<>''
BEGIN
IF not exists(select 1 from sys.SysObjects where name=@IndexName and (xtype=N'UQ' OR xtype=N'PK') )
BEGIN
RAISERROR('索引不存在,請輸入正確的索引名稱!',16,3);
RETURN -1;
END
END

--如果表名爲空表示所有表,如果索引爲空表示所有索引
--默認查詢所有表,所有索引,所有百分比

SET @Sql='SELECT D.name+''.''+object_name(a.object_id) [TableName] ,a.index_id ,B.name [IndexName] ,avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats ( DB_ID() , NULL , NULL, NULL, NULL ) AS A
JOIN sys.indexes AS B ON a.object_id = b.object_id AND a.index_id = b.index_id
inner JOIN sys.tables AS C ON a.object_id=C.object_id
inner JOIN sys.schemas AS D ON C.schema_id=D.schema_id
WHERE a.index_id > 0 '

IF isnull(@Scheme,'') <>''
BEGIN
SET @Sql +=' and D.name= '''+@Scheme+''' ';
END
IF isnull(@TableName,'')<>''
BEGIN
SET @Sql +=' and object_name(a.object_id)= '''+@TableName+''' ';
END
IF isnull(@IndexName,'')<>''
BEGIN
SET @Sql +=' and B.name= '''+@IndexName+''' ';
END

IF isnull(@FragmentPercent,0)>0
BEGIN
SET @Sql +=' and avg_fragmentation_in_percent>= '+convert(nvarchar(10),@FragmentPercent)+' ';
END

INSERT INTO @Tables
EXEC (@Sql)
select '重建前',* from @Tables

DECLARE cur cursor for
select TableName, IndexName from @Tables
OPEN cur
DECLARE @tbName NVARCHAR(100),@IXName NVARCHAR(200)
FETCH NEXT FROM cur INTO @tbName,@IXName
WHILE(@@fetch_status=0)
BEGIN
SET @RebuildSql='alter index ['+@IXName+'] on '+@tbName+' rebuild' --要加上[],否則索引裏有空格會報錯
EXEC (@RebuildSql)
print @RebuildSql
FETCH NEXT FROM cur INTO @tbName,@IXName
END
CLOSE cur
DEALLOCATE cur

--重建後查詢
delete @Tables
INSERT INTO @Tables
EXEC (@Sql)
select '重建後',* from @Tables

Print N'執行完畢!';
return 0;
END
GO

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章