MSSQL中整理索引碎片的存储过程

IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sp_defragment_indexes]') AND type in (N'P', N'PC'))
  Drop procedure sp_defragment_indexes
GO

EXEC dbo.sp_executesql @statement = N'ALTER PROCEDURE [dbo].[sp_defragment_indexes] @maxfrag DECIMAL, @LIKENAME VARCHAR(20)

AS --王成辉翻译整理,转贴请注明出处

	--声明变量
	SET NOCOUNT ON
	DECLARE @tablename VARCHAR (128)
	DECLARE @execstr VARCHAR (255)
	DECLARE @objectid INT
	DECLARE @objectowner VARCHAR(255)
	DECLARE @indexid INT
	DECLARE @frag DECIMAL
	DECLARE @indexname CHAR(255)
	DECLARE @dbname sysname
	DECLARE @tableid INT
	DECLARE @tableidchar VARCHAR(255)

	--检查是否在用户数据库里运行

	SELECT @dbname = db_name()
	IF @dbname IN (''master'', ''msdb'', ''model'', ''tempdb'')
	BEGIN
		PRINT ''This procedure should not be run in system databases.''
		RETURN
	END

	--第1阶段:检测碎片

	--声明游标
	if @LIKENAME=''''
	  DECLARE tables CURSOR FOR
	  SELECT convert(varchar,so.id)
        FROM sysobjects so
	    JOIN sysindexes si ON so.id = si.id
	  WHERE so.type =''U'' AND si.indid < 2 AND si.rows > 0
	else
	  DECLARE tables CURSOR FOR
	  SELECT convert(varchar,so.id)
        FROM sysobjects so
	    JOIN sysindexes si ON so.id = si.id
	  WHERE so.type =''U'' AND si.indid < 2 AND si.rows > 0 AND so.name LIKE ''%''+@LIKENAME+''%''

	-- 创建一个临时表来存储碎片信息
	CREATE TABLE #fraglist (
		ObjectName CHAR (255),
		ObjectId INT,
		IndexName CHAR (255),
		IndexId INT,
		Lvl INT,
		CountPages INT,
		CountRows INT,
		MinRecSize INT,
		MaxRecSize INT,
		AvgRecSize INT,
		ForRecCount INT,
		Extents INT,
		ExtentSwitches INT,
		AvgFreeBytes INT,
		AvgPageDensity INT,
		ScanDensity DECIMAL,
		BestCount INT,
		ActualCount INT,
		LogicalFrag DECIMAL,
		ExtentFrag DECIMAL)

	--打开游标
	OPEN tables
	-- 对数据库的所有表循环执行dbcc showcontig命令
	FETCH NEXT FROM tables
   	 INTO @tableidchar WHILE @@FETCH_STATUS = 0

	BEGIN
	--对表的所有索引进行统计
	INSERT INTO #fraglist
		EXEC (''DBCC SHOWCONTIG ('' + @tableidchar + '') WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS'')
		FETCH NEXT
		FROM tables INTO @tableidchar
	END

	-- 关闭释放游标
	CLOSE tables
	DEALLOCATE tables

	-- 为了检查,报告统计结果
	SELECT * FROM #fraglist ORDER BY ObjectName 
	-- 第2阶段: (整理碎片) 为每一个要整理碎片的索引声明游标
	DECLARE indexes CURSOR FOR
	  SELECT ObjectName, ObjectOwner = user_name(so.uid), ObjectId, IndexName, ScanDensity
	    FROM #fraglist f JOIN sysobjects so ON f.ObjectId=so.id
       WHERE ScanDensity <= @maxfrag AND INDEXPROPERTY (ObjectId, IndexName, ''IndexDepth'') > 0
	   ORDER BY ScanDensity 
	-- 输出开始时间
--	SELECT ''Started defragmenting indexes at '' + CONVERT(VARCHAR,GETDATE(),113)
        Print ''Started defragmenting indexes at '' + CONVERT(VARCHAR,GETDATE(),113)

	--打开游标
	OPEN indexes
	--循环所有的索引
	FETCH NEXT
	FROM indexes
	INTO @tablename, @objectowner, @objectid, @indexname, @frag
	WHILE @@FETCH_STATUS = 0
	BEGIN
		SET QUOTED_IDENTIFIER ON
		SELECT @execstr = ''DBCC DBREINDEX ('' + '''''''' +RTRIM(@objectowner) + ''.'' + RTRIM(@tablename) + '''''''' +
		'', ['' + RTRIM(@indexname) + '']) WITH NO_INFOMSGS''
--		SELECT ''Now executing: ''
--		SELECT(@execstr)
        Print ''Now executing: ''+ @execstr
		EXEC (@execstr)
		SET QUOTED_IDENTIFIER OFF
	FETCH NEXT
	 FROM indexes
	 INTO @tablename, @objectowner, @objectid, @indexname, @frag
	END

	-- 关闭释放游标
	CLOSE indexes
	DEALLOCATE indexes

	-- 报告结束时间
--	SELECT ''Finished defragmenting indexes at '' + CONVERT(VARCHAR,GETDATE(),113)
        Print ''Finished defragmenting indexes at '' + CONVERT(VARCHAR,GETDATE(),113)

	-- 删除临时表
	DROP TABLE #fraglist' 
END
GO

GRANT EXECUTE ON  SP_DEFRAGMENT_INDEXES TO PUBLIC
GO


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值