欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MSSQL自动重建出现碎片的索引的方法分享

程序员文章站 2023-10-20 10:54:13
1.索引碎片的产生? 由于在表里大量的插入、修改、删除操作而使索引页分裂。如果索引有了高的碎片,有两种情况,一种情况是扫描索引需要花费很多的时间,另一种情况是在查询的时候...

1.索引碎片的产生?

由于在表里大量的插入、修改、删除操作而使索引页分裂。如果索引有了高的碎片,有两种情况,一种情况是扫描索引需要花费很多的时间,另一种情况是在查询的时候索引根本不使用索引,都会导致性能降低。

2.碎片类型分为:

2.1 内部破碎

由于索引页里的数据插入或修改操作而发生,以数据作为稀疏矩阵的形式的分布而结束,这将导致数据页的增加,从而增加查询时间。

2.2外部破碎

由于索引/数据页的数据插入或修改而发生,以页码分离和在文件系统里不连贯的新的索引页的分配而结束,数据库服务器不能利用预读操作的优点,因为:下一个相关联的数据页不临近,而且这些相关连的下面的页码可能在数据文件的任何地方。

自动重建发生碎片的索引

在数据中新建碎片整理存储过程

复制代码 代码如下:

-- ================================================
-- template generated from template explorer using:
-- create procedure (new menu).sql
--
-- use the specify values for template parameters
-- command (ctrl-shift-m) to fill in the parameter
-- values below.
--
-- this block of comments will not be included in
-- the definition of the procedure.
-- ================================================
set ansi_nulls on
go
set quoted_identifier on
go
-- =============================================
-- author:  <author,,wuxiangqian>
-- create date: <create date,2014-05-16>
-- description: <description,重建出现碎片的索引>
-- =============================================
alter procedure usp_ims_defragment_indexes
as
--声明变量
set nocount on
declare @tablename varchar (128) --表名称(已发生索引碎片)
declare @execstr varchar (255) --执行重建索引的语句
declare @indexname char(255) --索引名称
declare @dbname sysname --数据库名称
declare @dbnamechar varchar(20) --数据库名称
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 else
begin
set @dbnamechar = 'dbname'
end

--第1阶段:检测碎片
--声明游标
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

-- 创建一个临时表来存储碎片信息
create table #fraglist (
tablename char (255),
indexname char (255))

--打开游标
open tables

-- 对数据库的所有表循环执行dbcc showcontig命令
fetch next
from tables
into @tableidchar

while @@fetch_status = 0
begin
--对表的所有索引进行统计
insert into #fraglist

exec ('select object_name(dt.object_id) as tablename,si.name as indexname from '+
' (select object_id,index_id,avg_fragmentation_in_percent,avg_page_space_used_in_percent '+
' from sys.dm_db_index_physical_stats(db_id('''+@dbnamechar+'''),object_id('''+@tableidchar+''')'+
',null,null,''detailed'') where index_id<>0)as dt inner join sys.indexes si'+
' on si.object_id=dt.object_id and si.index_id=dt.index_id and '+
' dt.avg_fragmentation_in_percent>10'+
' and dt.avg_page_space_used_in_percent<75 order by dt.avg_fragmentation_in_percent desc')
fetch next
from tables
into @tableidchar
end

-- 关闭释放游标
close tables
deallocate tables

-- 为了检查,报告统计结果
select * from #fraglist

--第2阶段: (整理碎片) 为每一个要整理碎片的索引声明游标
declare indexes cursor for
select tablename, indexname
from #fraglist
-- 输出开始时间
select 'started defragmenting indexes at ' + convert(varchar,getdate())
--打开游标
open indexes
--循环所有的索引
fetch next
from indexes
into @tablename, @indexname
while @@fetch_status = 0
begin
set quoted_identifier on
select @execstr = 'alter index '+@indexname+' on '+@tablename+' rebuild with(fillfactor=90,online=on)'

select 'now executing: '
select(@execstr)
exec (@execstr)
set quoted_identifier off
fetch next
from indexes
into @tablename, @indexname
end
-- 关闭释放游标
close indexes
deallocate indexes

-- 报告结束时间
select 'finished defragmenting indexes at ' + convert(varchar,getdate())

-- 删除临时表
drop table #fraglist
go

go

设置定时执行步骤

(1)启动【sql server management studio】,在【对象资源管理器】窗口里选择【管理】——【维护计划】选项。

(2)右击【维护计划】,在弹出的快捷菜单里选择【维护计划向导】选项,弹出如图所示的【维护计划向导】对话框,单击【下一步】按钮

(3)弹出如图所示【选择目标服务器】对话框,在【名称】文本框里可以输入维护计划的名称;在【说明】文本框里可以输入维护计划的说明文字;【在服务器】文本框里可以输入要使用的服务器名;最后选择正确的身份证信息,单击【下一步】按钮。

(4)弹出如图所示【选择维护任务】对话框,在该对话框中可以选择执行sql维护任务,插入执行存储过程语句

复制代码 代码如下:

use [dbname]

go

exec [dbo].[usp_ims_defragment_indexes]

(5)指定任务执行计划