首页 > 数据库 >SqlServer运维——重建索引

SqlServer运维——重建索引

时间:2024-11-20 09:22:16浏览次数:1  
标签:index name 运维 IX SqlServer 索引 id 重建

目录

0. 什么是重建索引

如果表中记录频繁地被删除或插入,尽管表中的记录总量保持不变,索引空间的使用量会不断增加。

虽然记录从索引中被删除,但是该记录索引项的使用空间不能被重新使用。

因此,如果表变化不定,索引空间量会不断增加,不论表中记录数量是否增加,这是因为索引中无效空间会增加。

要回收那些曾被删除记录使用的空间,则需要重建索引。

1. 什么时候需要重建索引

  • 在SQL Server中,可以通过查询系统视图和动态管理视图来判断是否需要重建索引。以下是一个基本的SQL脚本,用于检查各个索引的健康状况,并据此推荐是否需要重建索引:

  • 这个查询会返回所有平均碎片率大于1%的非主键索引,并根据碎片率的级别给出重建索引的建议。如果碎片率严重(大于20%),并且索引不是主键索引,则推荐重建该索引。
    请注意,这个查询使用了sys.dm_db_index_physical_stats函数,它提供了索引碎片的实时信息。该查询还排除了主键索引,因为主键索引的碎片一般不会导致性能问题,除非表结构发生了显著变化。根据实际情况,可能需要调整阈值和排除条件。

  • 注:可以参考这篇文章研究关于索引优化的相关知识,:mssql 优化之索引部分

SELECT OBJECT_NAME(i.object_id) AS 'Table Name',
       i.name AS 'Index Name',
       i.type_desc AS 'Index Type',
       avg_fragmentation_in_percent,
       CASE
           WHEN avg_fragmentation_in_percent > 10.0 THEN
               'HEAVILY_FRAGMENTED'
           WHEN avg_fragmentation_in_percent > 2.0 THEN
               'MODERATELY_FRAGMENTED'
           WHEN avg_fragmentation_in_percent > 1.0 THEN
               'LIGHTLY_FRAGMENTED'
           ELSE
               'NOT_FRAGMENTED'
       END AS 'Fragmentation Level',
       CASE
           WHEN avg_fragmentation_in_percent > 20.0
                AND i.name NOT LIKE 'PK_%' THEN
               'REBUILD'
           ELSE
               'NONE'
       END AS 'Recommended Action'
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') t
    INNER JOIN sys.indexes i
        ON t.object_id = i.object_id
           AND t.index_id = i.index_id
WHERE avg_fragmentation_in_percent > 1.0
      AND i.name NOT LIKE 'PK_%';

2. 如何重建索引:重建索引和删除原索引后再创建新索引

  • 重建索引有两种方法:一种是最简单的,删除原索引,然后重建;第二种是使用ALTER INDEX … REBUILD命令对索引进行重建。

  • ‌ALTER INDEX REBUILDDrop Index……;Create Index……区别:

    • ‌ALTER INDEX REBUILD‌:这种方法不需要删除原有的索引,而是直接在原有索引的基础上进行重建。重建过程中,系统会使用原索引的叶子节点作为新索引的数据来源,这样可以减少I/O操作和排序工作‌

    • 删除索引之后再创建:在删除原有索引后,需要重新分配存储空间来创建新的索引。这可能需要更多的磁盘空间,尤其是在磁盘空间有限的情况下‌

    • 删除索引之后再创建,在创建索引的时候需要排序,而重建索引(‌ALTER INDEX REBUILD)不需要再重新排序

    • 重建索引(‌ALTER INDEX REBUILD) 在重建的过程中的,并不影响查询语句使用现有的索引

  • 删除索引之后再创建的使用场景:

    • 在需要往表中插入大量数据时,可以先删除表现有的索引,之后在创建索引。这样做的好处:
      • 提高数据插入的速度
      • 更有效地使用索引空间
  • 关于DBCC DBREINDEX重建索引

    • 此方法一般在SqlServer2000中使用,重建索引(单个或多个)。(官方文档:后续版本的 Microsoft SQL Server 将删除该功能。请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。 改用 ALTER INDEX。)

3. 如何重建索引

  • 首要说明:数据库优化(重建索引)执行期间耗费系统资源高、执行时间一般较长,建议在空闲时间操作。
  1. 对某个表进行重建索引
ALTER INDEX ALL ON YourTableName REBUILD
  • 说明:如果重建时有其他用户在对这个表操作,建议使用带ONLINE参数以减少加锁问题
ALTER INDEX index_name REBUILD ONLINE;
  1. 查询数据库中的所有的用户创建的表对象
SELECT SCHEMA_NAME(schema_id) AS SchemaName, name AS TableName
FROM  sys.objects
WHERE type='U' --表
      AND is_ms_shipped=0; --表示用户自行创建的,非Microsoft创建的

--说明:官方文档中的 'U'就是代表用户定义的表

说明:
is_ms_shipped是 SQL Server 中的一个系统元数据属性,用来表示数据库对象(如表、视图、存储过程等)是否由 Microsoft 提供。
如果值为 1,那么这个对象是由 Microsoft 提供的;
如果值为 0,那么这个对象是用户创建的。

  1. 基于所有的表对象创建重建索引的动态SQL语句
DECLARE @SQLSTR NVARCHAR(MAX) = N'';
SELECT @SQLSTR = @SQLSTR + +N'ALTER INDEX ALL ON  ' + name + N' REBUILD;'
FROM sys.tables
WHERE type = 'U'
      AND is_ms_shipped = 0;
PRINT @SQLSTR;
--EXEC @SQLSTR; --执行动态生成的更新索引的SQL语句
  1. 关于金蝶云星空的中创建所有表索引的动态SQL语句
  • 基于上述的创建动态SQL的脚本,这里添加两个筛选条件,筛选出T_开头的表,并排除TMP_开头的
DECLARE @SQLSTR NVARCHAR(MAX) = N'';
SELECT @SQLSTR = @SQLSTR + +N'ALTER INDEX ALL ON  ' + name + N' REBUILD;'
FROM sys.tables
WHERE type = 'U'
      AND is_ms_shipped = 0
      AND (name LIKE 'T_%')
      AND (name NOT LIKE 'TMP%');
PRINT @SQLSTR;
--EXEC @SQLSTR;
  1. 更新统计信息

使用UPDATE STATISTICS命令来更新某个表的统计信息。这有助于查询优化器在执行查询时生成更准确的查询计划。

在索引进行了重大变更的情况下执行更新统计信息过程

  • 对某个表更新统计信息
UPDATE STATISTICS YourTableName;
  • 生成所有的表的更新统计信息的动态SQL
DECLARE @SQLSTR1 NVARCHAR(MAX);
SET @SQLSTR1 = N'';
SELECT @SQLSTR1 = @SQLSTR1 + +N'UPDATE STATISTICS ' + name + N';'
FROM sys.objects
WHERE type = 'U'
      AND is_ms_shipped = 0
PRINT @SQLSTR1;
--EXEC @SQLSTR1
  • 关于金蝶云星空生成所有表的更新统计信息的动态SQL
    • 筛选出T_开头的表,并排除TMP_开头的
DECLARE @SQLSTR1 NVARCHAR(MAX);
SET @SQLSTR1 = N'';
SELECT @SQLSTR1 = @SQLSTR1 + +N'UPDATE STATISTICS ' + name + N';'
FROM sys.objects
WHERE type = 'U'
      AND is_ms_shipped = 0
      AND (name LIKE 'T_%')
      AND (name NOT LIKE 'TMP%');
PRINT @SQLSTR1;
--EXEC @SQLSTR1

4. 创建重建索引的定时作业

5. 附录

  1. 查询数据库中所有表的索引,以及创建与删除该索引的语句
--生成表索引的创建删除语句
WITH    TB
          AS ( SELECT   TB.object_id ,
                        Schema_name = Sch.name ,
                        table_name = TB.name
               FROM     sys.tables TB
                        INNER JOIN sys.schemas Sch ON TB.schema_id = Sch.schema_id
               WHERE    TB.is_ms_shipped = 0
             ),
        IXC
          AS ( SELECT   IXC.object_id ,
                        IXC.index_id ,
                        IXC.index_column_id ,
                        IXC.is_descending_key ,
                        IXC.is_included_column ,
                        column_name = C.name
               FROM     SYS.index_columns IXC
                        INNER JOIN SYS.columns C ON IXC.object_id = C.object_id
                                                    AND IXC.column_id = C.column_id
             ),
        IX
          AS ( SELECT   IX.object_id ,
                        index_name = IX.name ,
                        index_type_desc = IX.type_desc ,
                        IX.is_unique ,
                        IX.is_primary_key ,
                        IX.is_unique_constraint ,
                        IX.is_disabled ,
                        index_columns_TEMP = STUFF(IXC_COL.index_columns, 1, 1,
                                                   N'') ,
                        index_columns = CASE WHEN IXC_COL_INCLUDE.index_columns_includes IS NOT NULL
                                             THEN STUFF(LEFT(IXC_COL.index_columns,
                                                             DATALENGTH(IXC_COL.index_columns)
                                                             - DATALENGTH(IXC_COL_INCLUDE.index_columns_includes)),
                                                        1, 1, N'')
                                             ELSE STUFF(IXC_COL.index_columns,
                                                        1, 1, N'')
                                        END ,
                        index_columns_includes = STUFF(IXC_COL_INCLUDE.index_columns_includes,
                                                       1, 1, N'')
               FROM     sys.indexes IX
                        CROSS APPLY ( SELECT    index_columns = ( SELECT
                                                              N','
                                                              + QUOTENAME(column_name)
                                                              FROM
                                                              IXC
                                                              WHERE
                                                              object_id = IX.object_id
                                                              AND index_id = IX.index_id
                                                              ORDER BY index_column_id
                                      FOR       XML PATH('') ,
                                                    ROOT('r') ,
                                                    TYPE      
   ).value('/r[1]', 'nvarchar(max)')
                                    ) IXC_COL
                        OUTER APPLY ( SELECT    index_columns_includes = ( SELECT
                                                              N','
                                                              + QUOTENAME(column_name)
                                                              FROM
                                                              IXC
                                                              WHERE
                                                              object_id = IX.object_id
                                                              AND index_id = IX.index_id
                                                              AND is_included_column = 1
                                                              ORDER BY index_column_id
                                      FOR       XML PATH('') ,
                                                    ROOT('r') ,
                                                    TYPE      
   ).value('/r[1]', 'nvarchar(max)')
                                    ) IXC_COL_INCLUDE
               WHERE    index_id > 0
             )
    SELECT  DB_NAME() AS N'数据库名' ,
            TB.Schema_name AS N'架构' ,
            TB.table_name AS N'表名' ,
            IX.index_name AS N'索引名' ,
            IX.index_type_desc AS N'索引类型' ,
            IX.is_unique AS N'是否唯一索引' ,
            IX.is_primary_key AS N'是否主键' ,
            IX.is_unique_constraint AS N'是否唯一约束' ,
            IX.is_disabled AS N'是否禁用索引' ,
            IX.index_columns AS N'索引列' ,
            IX.index_columns_includes AS N'索引包含列' ,
            N'CREATE INDEX ' + N'[' + IX.index_name + N']' + N' ON ' + N'['
            + QUOTENAME(DB_NAME()) + N'.' + QUOTENAME(TB.SCHEMA_NAME) + N'.'
            + QUOTENAME(TB.table_name) + N'(' + IX.index_columns + N')'
            + CASE WHEN IX.index_columns_includes IS NOT NULL
                   THEN CHAR(13) + N'INCLUDE (' + IX.index_columns_includes
                        + N')'
                   ELSE N''
              END AS N'创建索引' ,
            N'DROP INDEX ' + QUOTENAME(IX.index_name) + N' ON  '
            + QUOTENAME(DB_NAME()) + N'.' + QUOTENAME(TB.SCHEMA_NAME) + N'.'
            + QUOTENAME(TB.table_name) AS N'删除索引'
    FROM    TB
            INNER JOIN IX ON TB.object_id = IX.object_id
    --and IX.index_type_desc<>'CLUSTERED'
    ORDER BY Schema_name ,
             table_name ,
             IX.index_name

  1. 金蝶云星空官方提供的重建索引的脚本
DECLARE @sql NVARCHAR(1000) =N'DBCC DBREINDEX(@TABLE_NAME) WITH NO_INFOMSGS';
DECLARE @tbl NVARCHAR(1000) =N'';
DECLARE tblcur CURSOR FOR
SELECT [name]
FROM  sys.tables
WHERE [name] NOT LIKE 'TMP%' AND [name] NOT LIKE 'Z[_]%'
ORDER BY 1
FOR READ ONLY;
OPEN tblcur;
FETCH NEXT FROM tblcur
INTO  @tbl;
WHILE @@FETCH_STATUS=0 BEGIN
      EXEC sp_executesql @sql, N'@table_name NVARCHAR(1000)', @tbl;
      PRINT '表重建索引成功:'+@tbl;
      FETCH NEXT FROM tblcur
      INTO  @tbl;
END;
CLOSE tblcur;
DEALLOCATE tblcur;
PRINT '全部执行完成!';

简单手工运行版本:

DECLARE @sql AS VARCHAR(MAX) ='';
SELECT @sql=@sql+'dbcc dbreindex(['+name+']);'+CHAR(13)+CHAR(10)
FROM  sys.tables
WHERE name NOT LIKE 'tmp%' AND name NOT LIKE 'z%';
EXEC(@sql);
  1. 实施方提供的更新金蝶数据库索引的完整脚本
  • 除了其使用的sysobjects对象,和上文中的一致
--重建索引 
DECLARE @SQLSTR NVARCHAR(MAX)
SET @SQLSTR=''
SELECT @SQLSTR=@SQLSTR++'ALTER INDEX ALL ON  '+NAME+' REBUILD;'FROM SYSOBJECTS WHERE XTYPE='U'AND(NAME LIKE'T_%')AND(NAME NOT LIKE'TMP%')
EXEC (@SQLSTR)
--更新统计信息
DECLARE @SQLSTR1 NVARCHAR(MAX)
SET @SQLSTR1=''
SELECT @SQLSTR1=@SQLSTR1++'UPDATE STATISTICS '+NAME+';'FROM SYSOBJECTS WHERE XTYPE='U'AND(NAME LIKE'T_%')AND(NAME NOT LIKE'TMP%')
EXEC (@SQLSTR1)

标签:index,name,运维,IX,SqlServer,索引,id,重建
From: https://www.cnblogs.com/shanzhiming/p/18540222

相关文章

  • #渗透测试#SRC漏洞挖掘#网络运维# 黑客脚本编写05之字符串运算符与逻辑运算
    免责声明本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停止本文章阅读。                            ......
  • BING搜索引擎去广告
    一、问题现状在浏览器地址栏搜关键字会有广告,我用的BING最他妈恶心的是,点到广告条目左边的空白区,一样进入广告二、解决办法查阅资料,原因是bing的url被添加了FORM参数https://cn.bing.com/search?q=<关键字>&PC=<>&FORM=<小可爱>进入浏览器安装目录cmdergrep-Hnr'&FORM=......
  • 基于 LLM 的智能运维 Agent 系统设计与实现
    摘要本文详细介绍了一个基于大语言模型(LLM)的智能运维Agent系统的设计与实现。该系统采用多Agent协同的架构,通过事件驱动的方式实现了自动化运维流程。系统集成了先进的AI能力,能够实现故障自动诊断、预测性维护、知识沉淀等核心功能。一、运维Agent架构设计在设计智能......
  • MySQL 日常运维命令总结(一)
    一、连接数据库使用root用户和指定密码连接本地MySQL数据库root@localhost:(none)>`mysql-uroot-p'password'`指定主机和端口连接MySQL数据库root@localhost:(none)>`mysql-uroot-p'password'-h127.0.0.1-P3306`使用指定的套接字文件连接MySQL数据......
  • 运维系列:Docker学习笔记(3)-- 如何使用Dockerfile构建镜像
    Docker学习笔记(3)--如何使用Dockerfile构建镜像Docker学习笔记(3)--如何使用Dockerfile构建镜像1.Dockerfile的书写规则及指令使用方法(1)FROM(指定基础image)该指令有两种格式:(2)MAINTAINER(用来指定镜像创建者信息)格式:(3)RUN(安装软件用)该指令有两种格式:......
  • MySQL进阶:深入索引 - 空间索引
    ......
  • MySQL进阶:深入索引 - 函数和表达式索引
    ......
  • SqlServer数据库恢复备份数据的方法
    一、如何备份 二、开始还原当时在公司是要将阿里云的sqlserver中的数据备份一份到公司内网数据库,并将数据恢复到公司内网SqlServer数据库,当我按照原库的要求创建了新的空库。在SSMS控制台还原的时候,它竟然报错,报:system.data.sqlclient.Sqlerror:备份集中的数据库备份与现......
  • 数据结构(倒排索引)
    倒排索引和正排索引倒排索引是什么?倒排索引也被称作反向索引(invertedindex),是用于提高数据检索速度的一种数据结构,空间消耗比较大。倒排索引首先将检索文档进行分词得到多个词语/词条,然后将词语和文档ID建立关联,从而提高检索效率。分词就是对一段文本,通过规则或者算......
  • Elasticsearch集群拒绝请求:索引磁盘使用超限
    这是一个典型的Elasticsearch集群因为磁盘空间不足而触发的保护机制,导致索引被设置为只读模式(read-only-allow-delete​)。以下是解决这个问题的步骤:释放磁盘空间:您需要清理服务器上的磁盘空间,删除不必要的旧索引或者日志文件,以降低磁盘使用率。可以使用以下命令删除不需要的索......