SQL索引碎片的产生,处理过程。「建议收藏」

SQL索引碎片的产生,处理过程。「建议收藏」本文参考 https://www.cnblogs.com/CareySon/archive/2011/12/22/2297568.html https://www.jb51.net/softjc/12

本文参考

https://www.cnblogs.com/CareySon/archive/2011/12/22/2297568.html

https://www.jb51.net/softjc/126055.html

https://docs.microsoft.com/zh-cn/sql/relational-databases/system-dynamic-management-views/sys-dm-db-index-physical-stats-transact-sql?view=sql-server-ver15

本文需要对“索引”和MSSQL中数据的“存储方式”有一定了解。

软件经常在使用一段时间过后会无缘无故卡顿,这是因为在数据库(MSSQL)频繁的插入和更新的操作过程中会产生分页,在分页的过程中产生碎片导致的。所以,对于碎片需要定时的处理。基本上所有的办法都是基于对索引的重建和整理,只是方式不同。

  1. 删除索引并重建
  2. 使用DROP_EXISTING语句重建索引
  3. 使用ALTER INDEX REBUILD语句重建索引
  4. 使用ALTER INDEX REORGANIZE

以上方式各有优缺点,下面存储过程主要使用3,4

先看一个整理碎片的存储过程,然后采用作业的方式定时执行。

Create PROCEDURE [dbo].[proc_rebuild_index]
    @ret    INT OUTPUT
AS
SET NOCOUNT ON
BEGIN
    DECLARE @fldDefragFragment INT = 10;
    DECLARE @fldRebuildFragment INT = 30;
    DECLARE @fldMinPageCount INT = 1000;
    DECLARE @fldTable VARCHAR(256);
    DECLARE @fldIndex VARCHAR(256);
    DECLARE @fldPercent INT;
    DECLARE @Sql       VARCHAR(256);
    declare @DBID  int;
    BEGIN TRY
        SET @ret = -1;
        set @DBID = db_id();
        -- 获取索引碎片状况
        DECLARE curIndex CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY FOR
            SELECT 
                 TBL.NAME TABLE_NAME
                ,IDX.NAME INDEX_NAME
                ,AVGP.AVG_FRAGMENTATION_IN_PERCENT
            FROM SYS.DM_DB_INDEX_PHYSICAL_STATS(@DBID, NULL,NULL, NULL, "LIMITED") AS AVGP 
            INNER JOIN SYS.INDEXES AS IDX 
             ON AVGP.OBJECT_ID = IDX.OBJECT_ID 
            AND AVGP.INDEX_ID = IDX.INDEX_ID 
            INNER JOIN SYS.TABLES AS TBL 
             ON AVGP.OBJECT_ID = TBL.OBJECT_ID
            INNER JOIN SYS.DM_DB_PARTITION_STATS PS
             ON AVGP.OBJECT_ID = PS.OBJECT_ID
            AND AVGP.INDEX_ID = PS.INDEX_ID 
            WHERE
                AVGP.INDEX_ID >= 1 
            AND AVGP.AVG_FRAGMENTATION_IN_PERCENT >= @fldDefragFragment
            AND PS.RESERVED_PAGE_COUNT >= @fldMinPageCount;
        -- 打开游标
        OPEN curIndex;
        -- 获取游标
        FETCH NEXT FROM curIndex
        INTO @fldTable,@fldIndex,@fldPercent;
        WHILE @@FETCH_STATUS = 0
            BEGIN
                --碎片率大于30,重建索引
                IF @fldPercent >= @fldRebuildFragment
                    BEGIN
                        SET @Sql = "ALTER INDEX " + @fldIndex + " ON " + @fldTable + " REBUILD";
                        EXEC(@Sql);
                    END
                ELSE
                --碎片率小于30,重组索引
                    BEGIN
                        SET @Sql = "ALTER INDEX " + @fldIndex + " ON " + @fldTable + " REORGANIZE";
                        EXEC(@Sql);
                    END
                -- 获取游标
                FETCH NEXT FROM curIndex
                INTO @fldTable,@fldIndex,@fldPercent;
            END
        -- 关闭游标
        CLOSE curIndex;
        DEALLOCATE curIndex;
        SET @ret = 0;
    END TRY
    BEGIN CATCH
        SET @ret = -1;
        DECLARE @ErrorMessage    nvarchar(4000);
        DECLARE @ErrorSeverity    int;
        DECLARE @ErrorState        int;
        SELECT
              @ErrorMessage = ERROR_MESSAGE()
            , @ErrorSeverity  = ERROR_SEVERITY()
            , @ErrorState = ERROR_STATE();
        RAISERROR( @ErrorMessage, @ErrorSeverity, @ErrorState);
        RETURN;
    END CATCH;
END

代码100分

下面直观的看一下碎片产生的过程

代码100分--创建测试表
if object_id("test") is not null 
  drop table test
go
create table test
(
  col1 int, 
  col2 char(985),
  col3 varchar(10)
)
Go
--创建聚焦索引
create CLUSTERED index cix on test(col1);
go
--插入数据
declare @var int 
set @var=100
while (@var<900) 
begin
  insert into test(col1, col2, col3) 
  values (@var, "xxx", "")
  set @var=@var+100
end;
--查看页存储情况
select page_count, avg_page_space_used_in_percent, record_count,
       avg_record_size_in_bytes, avg_fragmentation_in_percent, fragment_count,
       * from [master].sys.dm_db_index_physical_stats(db_id(), OBJECT_ID("test"), null, null, "sampled")

SQL索引碎片的产生,处理过程。「建议收藏」 

–然后做更新操作后,继续查看页存储情况。

update test set col3="更新测试" where col1=100

SQL索引碎片的产生,处理过程。「建议收藏」

代码100分--再次插入数据后查看页存储情况
declare @var int 
set @var=100
while (@var<900) 
begin
  insert into test(col1, col2, col3) 
  values (@var, "插入测试", "")
  set @var=@var+100
end;

SQL索引碎片的产生,处理过程。「建议收藏」 

--下面看下对碎片整理之前和之后的IO
set statistics io on 
select * from test
alter index cix on test rebuild
select * from test 
set statistics io off

SQL索引碎片的产生,处理过程。「建议收藏」

 

 明显的逻辑读取减少了。从而提高了性能

 

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/10695.html

(0)
上一篇 2022-12-23
下一篇 2022-12-23

相关推荐

  • redis单机环境搭建「终于解决」

    redis单机环境搭建「终于解决」1. 安装版本 redis-2.8.18.tar.gz 2. 过程 3. 解压 tar xf xxx 4. 下载gcc,tcl 命令编译器 yum -y install gcc tcl (命令名字别…

    2023-03-20
    109
  • dbgen工具使用方法

    dbgen工具使用方法 本文将介绍dbgen多线程的使用方法: dbgen是用来生成TPCH 所需要的数据来使用的 TPCH :针对于数据库查询性能的压测方法 #:首先使用dbgen来生成数据 这里数据量业界有一个…

    2023-03-27
    113
  • Linux下二进制方式安装mysql5.7版本和系统优化「建议收藏」

    Linux下二进制方式安装mysql5.7版本和系统优化「建议收藏」本文主要介绍MySQL二进制软件包的安装/启动/关闭过程。 也许有人要问为什么要选择二进制的安装方式呢? 其实答案很简单,官方版本中已经把所有功能都配置好了,我们可以很方便地拿来使用。 官方MySQL

    2023-01-23
    100
  • Python实现1+1运算

    Python实现1+1运算Python作为一种强大的编程语言,具有高效、易学、多样化等特点,其应用范围广泛。本文将从多个方面阐述Python实现1+1运算的方法,包括基本语法、数据类型、运算符、变量、函数和模块等方面。

    2023-12-27
    58
  • 用Python正则表达式实现文本匹配和替换功能

    用Python正则表达式实现文本匹配和替换功能正则表达式是一种强大的文本处理工具,它可以帮助我们在一定规则下找到需要处理的内容,并进行相应的处理操作,比如查找、替换、匹配等。Python作为一门强大的编程语言,提供了re模块来支持正则表达式的操作。接下来,我们将从以下几个方面来详细阐述如何用Python正则表达式实现文本匹配和替换功能。

    2024-03-14
    30
  • mysql 如何实现读写分离_rac数据库数据读写

    mysql 如何实现读写分离_rac数据库数据读写Amoeba+Mysql实现数据库读写分离 一、Amoeba 是什么 Amoeba(变形虫)项目,专注 分布式数据库 proxy 开发。座落与Client、DB

    2023-05-31
    90
  • Hive sql常用函数「建议收藏」

    Hive sql常用函数「建议收藏」1.获取当前日期 如2020-13-22 current_date() 或者current_date 获取当前时间:from_unixtime(unix_timestamp()) –>返回格式

    2023-03-11
    98
  • 索引——谈谈你对索引的认识和理解「终于解决」

    索引——谈谈你对索引的认识和理解「终于解决」为什么要用索引? 一般的应用系统,读写比例在10:1左右,插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句的优化显然是

    2023-03-09
    94

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注