本文参考

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

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

--创建测试表
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')

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

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

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

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

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

SQL索引碎片的产生,处理过程。的更多相关文章

  1. sql索引碎片产生的原理 解决碎片的办法(sql碎片整理)(转)

    本文讲述了SQL SERVER中碎片产生的原理,内部碎片和外部碎片的概念.以及解决碎片的办法和填充因子.在数据库中,往往每一个对于某一方面性能增加的功能也会伴随着另一方面性能的减弱.系统的学习数据库知 ...

  2. sql索引碎片产生的原理 解决碎片的办法(sql碎片整理)

    本文讲述了SQL SERVER中碎片产生的原理,内部碎片和外部碎片的概念.以及解决碎片的办法和填充因子.在数据库中,往往每一个对于某一方面性能增加的功能也会伴随着另一方面性能的减弱.系统的学习数据库知 ...

  3. SQL索引碎片整理脚本

    原文发布时间为:2011-02-23 -- 来源于本人的百度文章 [由搬家工具导入] reindex是比较好的选择,速度快,但是他不能在线操作INDEXDEFRAG 比较慢,但是可以在线操作rebui ...

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

    SQL Server2005索引碎片分析和解决方法 本文作者(郑贤娴),请您在阅读本文时尊重作者版权. 摘要: SQL Server,为了反应数据的更新,需要维护表上的索引,因而这些索引会形成碎片.根 ...

  5. 提升SQL Server速度整理索引碎片

    转载:http://wenku.baidu.com/view/f64c8a707fd5360cba1adbea.html SQL Server2005索引碎片分析和解决方法   毫无疑问,给表添加索引 ...

  6. SQL Server索引进阶第十一篇:索引碎片分析与解决

    相关有关索引碎片的问题,大家应该是听过不少,也许也很多的朋友已经做了与之相关的工作.那我们今天就来看看这个问题. 为了更好的说明这个问题,我们首先来普及一些背景知识. 知识普及 我们都知道,数据库中的 ...

  7. sql server 表索引碎片处理

    DBCC SHOWCONTIG (Transact-SQL) SQL Server 2005 其他版本 更新日期: 2007 年 9 月 15 日 显示指定的表或视图的数据和索引的碎片信息. 重要提示 ...

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

    转:http://www.cnblogs.com/kissdodog/archive/2013/06/14/3135412.html 实际上,索引的维护主要包括以下两个方面: 页拆分 碎片 这两个问题 ...

  9. 转:sql server索引碎片和解决方法

    毫无疑问,给表添加索引是有好处的,你要做的大部分工作就是维护索引,在数据更改期间索引可能产生碎片,所以一些维护是必要的.碎片可能是你查询产生性能问题的来源. 那么到底什么是索引碎片呢?索引碎片实际上有 ...

随机推荐

  1. GRPC的metadata使用

    文章目录 一.简析 1.创建metadata 2.发送metadata 3.接收metadata 二.代码举例 1.proto文件编写 2.server端编写 3.client端编写 三.实际使用举例 ...

  2. 基于LAMP php7.1搭建owncloud云盘与ceph对象存储S3借口整合案例

    ownCloud简介 是一个来自 KDE 社区开发的免费软件,提供私人的 Web 服务.当前主要功能包括文件管理(内建文件分享).音乐.日历.联系人等等,可在PC和服务器上运行. 简单来说就是一个基于 ...

  3. 使用RSA加密方式加密文件

    链接:GITHUB 使用RSA对流进行加密并保存到文件中 缺点:速度非常的慢,加密大文件就等着吧 环境 VS2017 + C# 7.0 + .net framwork 4.7.2

  4. asp.net core 拦击器制作的权限管理系统DEMO

    效果图 没有登陆不会执行请求日期的方法,不管是否登陆都不允许访问请求时间方法 验证不通过是会进行转发到Home/error方法中, 代码附上: [Route("[controller]/[a ...

  5. 深入理解 Java 方法

    方法(有的人喜欢叫函数)是一段可重用的代码段.

  6. Seata 配置中心实现原理

    Seata 可以支持多个第三方配置中心,那么 Seata 是如何同时兼容那么多个配置中心的呢?下面我给大家详细介绍下 Seata 配置中心的实现原理. 配置中心属性加载 在 Seata 配置中心,有两 ...

  7. Day 02 作业

    作业 一 什么是编程? 基于编程语言的语法格式将自己脑中里想让计算机做的事,写到文件中. 二 简述计算机五大组成 控制器,运算器,存储器,输入设备,输出设备 三 操作系统有什么用? 操作系统直接与硬件 ...

  8. font-family与font-face的区别

    font-family:指定字体 设置后,电脑上无该字体时,观看网页不能显示该字体效果, 针对中文版操作系统,为保证网页效果,通常只指定:宋体.黑体.微软雅黑等系统上默认自带的字体. font-fac ...

  9. 毕业半年,买了一台MacBook Pro

    前言 只有光头才能变强. 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y 毕业半年,给自己买了一台MacBookPro 1 ...

  10. 利用用阿里云API实现DDNS

    前言 之前动态域名解析是用的是腾达路由器上集成的第三方动态解析服务花生壳,解析费用一年40元.后来觉得域名前缀不好,想换掉,花生壳需要重新购买新的域名解析费用,增加1条或者2条动态解析无所谓,万一以后 ...