索引碎片整理

USE [DBA_Maintenance]
IF EXISTS(SELECT 1 FROM sysobjects WHERE  xtype=‘P‘  AND name = ‘USP_Auto_IndexDefrag‘)
BEGIN
    DROP PROCEDURE USP_Auto_IndexDefrag
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[USP_Auto_IndexDefrag]
@Db_name nvarchar(256)
    WITH ENCRYPTION
AS
    BEGIN
    SET NOCOUNT ON

    declare @dbname nvarchar(256)
        ,@dbname_cur nvarchar(256)
        ,@SchemaName nvarchar(256)
        ,@TableName Nvarchar(256)
        ,@IndexName Nvarchar(512)
        ,@PctFrag decimal
        ,@Defrag nvarchar(max)
    DECLARE @SQL_TMP_SUB NVARCHAR(MAX)
    DECLARE @SQL_TMP NVARCHAR(MAX)

    set @dbname=@Db_name
    set @Db_name=N‘[‘+@Db_name+‘]‘

        if exists(select 1 from sys.objects where object_id =object_id(N‘#tmp‘)) Drop table #tmp;
        if exists(select 1 from sys.objects where object_id =object_id(N‘#tmp_sub‘)) Drop table #tmp_sub;

    create table #tmp_sub(database_id int,dbname nvarchar(32),tablename nvarchar(128),index_type_desc nvarchar(128))
    create clustered index ix_sub_db_id_tb_name_indexname on #tmp_sub(database_id,tablename,index_type_desc)
    create table #tmp(database_id int,dbname nvarchar(256),tablename nvarchar(256),indexname nvarchar(256),type_desc nvarchar(128),schemaname nvarchar(256),avgfragment decimal)
    create clustered index ix_db_id_tb_name_indexname on #tmp(database_id,tablename,type_desc)    

    SET @SQL_TMP_SUB=N‘USE‘ +@db_name+CHAR(13)+CHAR(10)+
    ‘insert into #tmp_sub(database_id,dbname,tablename,index_type_desc)
        select distinct c.database_id,c.name as dbname,b.name,‘‘CLUSTERED‘‘
         from
            sys.dm_db_index_physical_stats(DB_ID(‘‘‘+@dbname+‘‘‘),NULL,NULL,NULL,‘‘SAMPLED‘‘) as a
            join sys.tables as b on a.object_id=b.object_id
            join sys.databases as c on a.database_id=c.database_id
            join sys.all_columns d on d.object_id =a.object_id
            join sys.sysobjects e on d.object_id=e.id and e.xtype=‘‘U‘‘
            join sys.types f on d.user_type_id=f.user_type_id
        where  b.type_desc=‘‘USER_TABLE‘‘ and b.is_ms_shipped=0 and (d.max_length =-1
            OR (f.name in (‘‘image‘‘,‘‘text‘‘,‘‘ntext‘‘,‘‘xml‘‘,‘‘varbinary‘‘,‘‘binary‘‘)))‘+CHAR(13)+CHAR(10)+‘‘
    EXEC SP_EXECUTESQL @SQL_TMP_SUB, N‘@Db_name nvarchar(256),@dbname nvarchar(256)‘,@Db_name,@dbname

    SET @SQL_TMP=N‘ USE‘ +@db_name+CHAR(13)+CHAR(10)+
    ‘insert into #tmp(database_id,dbname,tablename,indexname,type_desc,schemaname,avgfragment)
        select  distinct d.database_id,d.name as dbname,c.name,b.name,b.type_desc,e.name,a.avg_fragmentation_in_percent
        from sys.dm_db_index_physical_stats(DB_ID(‘‘‘+@dbname+‘‘‘),NULL,NULL,NULL,‘‘SAMPLED‘‘) as a
            join sys.indexes as b on a.object_id=b.object_id and a.index_id=b.index_id
            join sys.tables as c on a.object_id=c.object_id
            join sys.databases as d on a.database_id=d.database_id
            join sys.schemas as e on c.schema_id=e.schema_id
            join sys.sysobjects f on c.object_id=f.id
            join sys.all_columns g on f.id=g.object_id
            join sys.types h on g.user_type_id=h.user_type_id
            where a.avg_fragmentation_in_percent >20
             and c.type=‘‘U‘‘ and f.xtype=‘‘U‘‘
             and c.is_ms_shipped=0 ‘+CHAR(13)+CHAR(10)+‘‘
    EXEC SP_EXECUTESQL @SQL_TMP, N‘@Db_name nvarchar(256),@dbname nvarchar(256)‘,@Db_name,@dbname
        ----------脱机重建索引
         declare @i_cur int=1
         declare @count int=0
            select @count=count(*)  from #tmp
                where  exists (select 1 from #tmp_sub b where database_id=b.database_id and tablename=b.tablename and type_desc=b.index_type_desc)
        if @count>=1
        begin
            while @i_cur<@count
            begin
                select  @dbname_cur=dbname,@TableName=tablename,@IndexName=indexname,@SchemaName=schemaname,@PctFrag=avgfragment
                 from
                    ( select row_number() over(order by indexname)rn,dbname,tablename,indexname,
                             schemaname,avgfragment
                           from #tmp
                           where  exists (select 1 from #tmp_sub b where database_id=b.database_id and tablename=b.tablename and type_desc=b.index_type_desc)
                    )ta where rn=@i_cur

                    if @PctFrag between 20.0 and 40.0
                         begin
                          set @Defrag=N‘ ALTER INDEX [‘+@IndexName+‘] ON [‘+@dbname_cur+‘].[‘+@SchemaName+‘].[‘+ @TableName +‘] REORGANIZE‘--重新组织索引页不删除索引
                          EXEC SP_EXECUTESQL @Defrag
                         end
                         else if @PctFrag>40.0
                         begin
                          SET @Defrag=N‘ ALTER INDEX [‘+@IndexName+‘] ON [‘+@dbname_cur+‘].[‘+@SchemaName+‘].[‘+ @TableName +‘] REBUILD WITH (ONLINE = OFF )‘--脱机重建索引。
                          EXEC SP_EXECUTESQL @Defrag
                         end
                    set @i_cur=@i_cur+1
            end
        end

        ----------联机重建索引
        declare @n_count int=0
        declare @n_i int=1

        select @count=count(*) from #tmp
            where not exists (select 1 from #tmp_sub b where database_id=b.database_id and tablename=b.tablename and type_desc=b.index_type_desc)
        if @count>=1
            begin
                WHILE @n_i<@count
                    begin
                        select @dbname_cur=dbname,@TableName=tablename,@IndexName=indexname,@SchemaName=schemaname,@PctFrag=avgfragment
                            from (  select row_number() over(order by indexname)rn,dbname,tablename,indexname,
                                     schemaname,avgfragment
                                   from #tmp
                                   where not exists (select 1 from #tmp_sub b where database_id=b.database_id and tablename=b.tablename and type_desc=b.index_type_desc)
                                   )tb  where rn=@n_i
                            if @PctFrag between 20.0 and 40.0
                                 begin
                                  set @Defrag=N‘ ALTER INDEX [‘+@IndexName+‘] ON [‘+@dbname_cur+‘].[‘+@SchemaName+‘].[‘+ @TableName +‘] REORGANIZE‘--重新组织索引页不删除索引
                                  EXEC SP_EXECUTESQL @Defrag
                                 end
                                 else if @PctFrag>40.0
                                 begin
                                  SET @Defrag=N‘ ALTER INDEX [‘+@IndexName+‘] ON [‘+@dbname_cur+‘].[‘+@SchemaName+‘].[‘+ @TableName +‘] REBUILD WITH (ONLINE = ON )‘--联机重建索引。即不锁定表重新创建索引
                                  EXEC SP_EXECUTESQL @Defrag
                                 end
                    set @n_i=@n_i+1
                    end
            end

        truncate table #tmp
        truncate table #tmp_sub
        drop table #tmp
        drop table #tmp_sub

    SET NOCOUNT OFF

END
时间: 2024-10-11 08:40:41

索引碎片整理的相关文章

SQL Server索引碎片整理实际操作记录

SQL Server 版本是 2008 R2. 查询数据库索引碎片情况的 SQL 语句(来源): SELECT OBJECT_NAME(ind.OBJECT_ID) AS TableName, ind.name AS IndexName, indexstats.index_type_desc AS IndexType, indexstats.avg_fragmentation_in_percent FROM sys.dm_db_index_physical_stats(DB_ID(), NULL

索引碎片整理(转)

索引碎片整理 一碎片种类 1 内部碎片,又称为平均页密度.是指索引正在占有超过它实际所需的空间大小. 它具有两面型:低百分比会对读取数据的查询产生负面影响,会涉及更多读取操作,因为如果页被填充满的话, 只需读取更少的页:另一方面,如果如果在创建索引时设置一个较低的填充因子,就可以避免当插入更多记录而不 必进行页拆分. 对应sys.dm_db_index_physical_stats的列avg_page_space_used_in_percent. 2 外部碎片,又称平均碎片百分比,或逻辑碎片.是

41.oracle索引,分析索引,索引碎片整理

概述 索引分为B树索引和位图索引.我们主要研究B树索引,B树索引如下图(图片源自网络): 索引是与表相关的一个可选结构,在逻辑上和物理上都独立于表数据,索引能优化查询,不能优化DML,oracle自动维护索引,频繁的DML操作反而会赢钱大量的索引卫华. 如果sql语句仅仅访问被索引的列,那么数据库只需从索引中读取数据,而不会读取表:如果该语句还要访问未被索引的列,那么数据库会使用rowid来查找表中的行,通常,为检索表数据,数据库以交换方式先读取索引块,然后读取对应的表. 索引的目的是减少IO

SQL Server数据库表索引碎片整理

在SQLServer数据库,通过DBCC ShowContig或DBCC ShowContig(表名)检查索引碎片情况,指导我们对其进行定时重建整理. 运行结果如下: 1 2 3 4 5 6 7 8 9 10 11 DBCC SHOWCONTIG 正在扫描 'tbModule' 表... 表: 'tbModule'(1845581613):索引 ID: 0,数据库 ID: 9 已执行 TABLE 级别的扫描. - 扫描页数.....................................

SQL Server2005索引碎片分析和解决方法

SQL Server2005索引碎片分析和解决方法 本文作者(郑贤娴),请您在阅读本文时尊重作者版权. 摘要: SQL Server,为了反应数据的更新,需要维护表上的索引,因而这些索引会形成碎片.根据工作量的特征,这些碎片会影响对应的工作性能.此文帮助决定是否需要整理碎片以改善性能的信息.SQL Serve提供一些命令来实现索引的碎片整理.这里比较其中两个命令:DBCC DBREINDEX 和 DBCC INDEXDEFRAG. 关键词: SQL Server;索引碎片;数据库优化毫无疑问,给

SQL Server索引的维护 - 索引碎片、填充因子 &lt;第三篇&gt;

实际上,索引的维护主要包括以下两个方面: 页拆分 碎片 这两个问题都和页密度有关,虽然两者的表现形式在本质上有所区别,但是故障排除工具是一样的,因为处理是相同的. 对于非常小的表(比64KB小得多),一个区中的页面可能属于多余一个的索引或表---这被称为混合区.如果数据库中有太多的小表,混合区帮助SQL Server节约磁盘空间. 随着表(或索引)增长并且请求超过8个页面,SQL Server创建专用于该表(或索引)的区并且从该区中分配页面.这样一个区被称为统一区,它可以为多达8个相同表或索引的

转: SQL Server索引的维护 - 索引碎片、填充因子

转:http://www.cnblogs.com/kissdodog/archive/2013/06/14/3135412.html 实际上,索引的维护主要包括以下两个方面: 页拆分 碎片 这两个问题都和页密度有关,虽然两者的表现形式在本质上有所区别,但是故障排除工具是一样的,因为处理是相同的. 对于非常小的表(比64KB小得多),一个区中的页面可能属于多余一个的索引或表---这被称为混合区.如果数据库中有太多的小表,混合区帮助SQL Server节约磁盘空间. 随着表(或索引)增长并且请求超过

转:索引碎片(代码好像不可用,待修改)

创建索引是为了在检索数据时能够减少时间,提高检索效率.创建好了索引,并且所有索引都在工作,但性能却仍然不好,那很可能是产生了索引碎片,你需要进行索引碎片整理. 1.什么是索引碎片? 由于表上有过度地插入.修改和删除操作,索引页被分成多块就形成了索引碎片,如果索引碎片严重,那扫描索引的时间就会变长,甚至导致索引不可用,因此数据检索操作就慢下来了. 有两种类型的索引碎片:内部碎片和外部碎片. 内部碎片:为了有效的利用内存,使内存产生更少的碎片,要对内存分页,内存以页为单位来使用,最后一页往往装不满,

SQL Server 索引碎片产生原理重建索引和重新组织索引

数据库存储本身是无序的,建立了聚集索引,会按照聚集索引物理顺序存入硬盘.既键值的逻辑顺序决定了表中相应行的物理顺序 多数情况下,数据库读取频率远高于写入频率,索引的存在 为了读取速度牺牲写入速度 页 为最小单位 8kb 区 物理连续的页(8页)的集合 内部碎片 数据库页内部产生的碎片,外部反之 碎片的产生: 有一个表里有8条数据,已经将一页填满,这个时候要插入第九条数据,页也就分裂了.这就产生了内部碎片.如下图所示(excel示意一下  懒癌晚期) 注: 不会将9单独分到第二页,索引B+树存储,