ssms 缺少索引信息_SQLServer索引重建
要点:
- 检查索引碎片fragmentation: average percentage, pagecount
- 采用ALTER INDEX REBUILD指令
- 手动设置Timeout参数
- 设置计数器以控制SSMS停止响应时间
- 增加暂停以释放被挂起的进程
- EXEC sp_who2以检查死锁
背景
有许多系统把部分逻辑写在数据库中,随着时间的流逝,数据和索引逐渐增加,因而数据库的性能将逐渐减小。
其中一个重要的影响因素是索引。
当数据和索引增加时,其碎片化程度也将随之增加。
根据微软的文档“Reorganizingand Rebuilding Indexes(https://docs.microsoft.com/en-us/previous-versions/sql/sql-server-2005/ms189858(v=sql.90))”, 当碎片化率在5%~30%时,我们应当使用REORGANIZE指令重组索引,当碎片化率超过30%时,我们应当REBUILD重建索引。
我们可以使用下述SQL列出所有碎片化率超过30%的索引:
-------------------------------------------------------------------------------------
SELECT dbschemas.[name]AS 'Schema'
,dbtables.[name] AS 'Table'
,dbindexes.[name] AS 'Index'
,indexstats.avg_fragmentation_in_percent
,indexstats.page_count
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) AS indexstats
INNER JOIN sys.tables dbtables ONdbtables.[object_id] =indexstats.[object_id]
INNER JOIN sys.schemas dbschemas ONdbtables.[schema_id] =dbschemas.[schema_id]
INNER JOIN sys.indexes AS dbindexesON dbindexes.[object_id]= indexstats.[object_id]
ANDindexstats.index_id =dbindexes.index_id
WHERE indexstats.database_id= DB_ID()
AND indexstats.avg_fragmentation_in_percent> 30
--ANDdbschemas.[name] = 'dbo'
--ANDdbtables.[name] = 'RPV_MAGPLANBEL'
--ORDERBY indexstats.page_count DESC;
ORDER BY indexstats.avg_fragmentation_in_percent DESC;
-------------------------------------------------------------------------------------
另有一个重要参数是page_count,即索引页数,每页约有8KB数据,因此当页数非常大时,意味着此索引的重建时间也会很长。
2. 需要考虑的因素
使用ALTER INDEX index_name还是ALTERINDEX ALL
使用ALTER INDEX index_name ON Table REBUILD只能重建指定索引。
使用ALTER INDEX ALL ON Table REBUILD能够重建此表的所有索引,但是也需要更长的等待时间,因此在重建过程中指向这些索引的新SQL将被挂起SUSPENDED等待。
手动设置远程timeout,以避免被服务器超时断开,如执行以下SQL:
EXEC sp_configure'remote query timeout', 600 ; -- 设置为600秒
RECONFIGURE ;
因为重建过程可能较长,超出默认的TIMEOUT,因此最好手动设置此项参数。
设置计数器以控制停止响应时间
即使我们在SSMS中通过PRINT()指令输出中间过程的信息,相关消息也只有在SQL指令块执行完毕之后才会显示。
在SQL执行过程中,消息框是空白的,因而在此期间我们无从得知SQL执行的具体情况。
因而最好将完整的执行过程分割成许多个小的过程,我们可以通过计数器予以控制。
现在我们修改一个查询碎片化的SQL,采用page_count逆向排序:
-------------------------------------------------------------------------------------
SELECT --dbschemas.[name] AS'Schema',
dbtables.[name]AS 'Table',
dbindexes.[name]AS 'Index',
indexstats.avg_fragmentation_in_percent,
indexstats.page_count
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) AS indexstats
INNER JOIN sys.tables dbtables ONdbtables.[object_id] =indexstats.[object_id]
INNER JOIN sys.schemas dbschemas ONdbtables.[schema_id] =dbschemas.[schema_id]
INNER JOIN sys.indexes AS dbindexesON dbindexes.[object_id]= indexstats.[object_id]
ANDindexstats.index_id =dbindexes.index_id
WHERE indexstats.database_id= DB_ID()
ANDindexstats.avg_fragmentation_in_percent > 30
ANDdbschemas.[name] ='dbo'
--ANDdbtables.[name] = 'RPV_MAGPLANBEL'
ANDdbindexes.[name] ISNOT NULL
ORDER BYindexstats.page_count DESC;
--ORDERBY indexstats.avg_fragmentation_in_percent DESC;
-------------------------------------------------------------------------------------
对于page count较大(如超过10万)的索引,我们可以每次只重建1个索引。
对于page count较小的索引,我们可以根据情况设置一个较大的计数器数据。
设置暂停以释放挂起的进程
当我们利用游标,在同一个进程中执行多个REBUILD指令时,我们应当在两个指令间设置至少5秒的暂停时间,此时间可用来释放被系统挂起的进程(这些进程会引用到正在重建的索引)。
相关SQL:
WAITFOR DELAY '00:00:05'; -- 暂停5秒
在REBUILD之前和进行中检查实时死锁deadlocks
相关指令:
EXECsp_who2
我们可以看到死锁的进程(Status=SUSPENDED, 或BlkBy IS NOT NULL), BlkBy指向引起死锁的进程。
只有确保无死锁发生时,才能执行REBUILD。
另一个检查死锁的SQL:
SELECT *
FROM sys.dm_exec_requests
WHERE DB_NAME(database_id) = 'KBS_FDM' –数据库名
AND blocking_session_id <>0;
3. 优化过的SQL:
-------------------------------------------------------------------------------------
Declare @getTables CURSOR; -- Cursor to list out allindexes have frag % > 30
Declare @TableName varchar(255);
Declare @IndexName varchar(255);
Declare @command nvarchar(4000); -- Detail ALTER INDEX command
DECLARE @DT NVARCHAR(50); -- Datetime to printout
DECLARE @i INT;-- Counter
-- setremote time out
EXEC sp_configure'remote query timeout', 600 ;
RECONFIGURE ;
SELECT @DT = CONVERT(NVARCHAR, GETDATE(), 121);--YYYY-MM-DD HH:MI:SS
PRINT(@DT);
PRINT('Rebuilding Index started.');
PRINT('');
--SET@getTables = CURSOR for SELECT name FROM sys.objects WHERE type = (N'U');
--EXECsp_who2 -- to check existing deadlock(BlkBy)
SET @i = 0;
SET @getTables = CURSOR for
SELECT --dbschemas.[name] AS'Schema',
dbtables.[name]AS 'TableName',
dbindexes.[name]AS 'IndexName'
--indexstats.avg_fragmentation_in_percent,
--indexstats.page_count
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) AS indexstats
INNER JOIN sys.tables dbtables ONdbtables.[object_id] =indexstats.[object_id]
INNER JOIN sys.schemas dbschemas ONdbtables.[schema_id] =dbschemas.[schema_id]
INNER JOIN sys.indexes AS dbindexesON dbindexes.[object_id]= indexstats.[object_id]
ANDindexstats.index_id =dbindexes.index_id
WHERE indexstats.database_id= DB_ID()
ANDindexstats.avg_fragmentation_in_percent > 30
ANDdbschemas.[name] ='dbo'
--AND dbtables.[name]= 'RPV_MAGPLANBEL'
ANDdbindexes.[name] ISNOT NULL
ORDER BY indexstats.page_count DESC;
--ORDERBY indexstats.avg_fragmentation_in_percent DESC;
OPEN @getTables;
FETCH NEXT FROM @getTables into @TableName,@IndexName;
--WHILE @@FETCH_STATUS= 0
WHILE @i < 1 AND @@FETCH_STATUS = 0-- Set @i to biggernumber when page count is getting smaller
BEGIN;
SELECT@DT = CONVERT(NVARCHAR, GETDATE(), 121);--YYYY-MM-DD HH:MI:SS
PRINT(@DT);
--set @command= N'ALTER INDEX ALL ON ' + @TableName + N' REBUILD;'; -- WITH (ONLINE=ON);'; for enterprise version only
set@command = N'ALTERINDEX ' + @IndexName + N' ON ' + @TableName + N' REBUILD;';
PRINT(@command);
--PRINT('');
--WAITFORDELAY '00:00:01';
BEGIN TRY
EXEC (@command);
SELECT@DT = CONVERT(NVARCHAR, GETDATE(), 121);--YYYY-MM-DD HH:MI:SS
PRINT(@DT);
PRINT('Rebuilding Indexcompleted.');
PRINT('');
END TRY
BEGIN CATCH
SELECT@DT = CONVERT(NVARCHAR, GETDATE(), 121);--YYYY-MM-DD HH:MI:SS
PRINT(@DT);
PRINT'CATCHED!';
END CATCH;
WAITFOR DELAY '00:00:05'; -- wait 5s to release suspended sessions
FETCH NEXT FROM @getTables into @TableName,@IndexName;
SET @i = @i + 1;
END;
CLOSE @getTables;
DEALLOCATE @getTables;
SELECT @DT = CONVERT(NVARCHAR, GETDATE(), 121);--YYYY-MM-DD HH:MI:SS
PRINT(@DT);
PRINT('All indexes rebuilt.');
-------------------------------------------------------------------------------------
4. 关于WITH(ONLINE=ON)参数
在运行ALTERINDEX (ALL) REBUILD指令时,有一个可选参数ONLINE。
如果设置ONLINE=ON,则在重建过程的大部分时间旧索引依然可用,因而对生产环境的影响较小,但是此参数仅适用于企业版SQL SERVER。
ssms 缺少索引信息_SQLServer索引重建相关推荐
- sqlserver和mysql索引结构_sqlserver 索引的一些总结
1.1.1 摘要 如果说要对数据库进行优化,我们主要可以通过以下五种方法,对数据库系统进行优化. 1. 计算机硬件调优 2. 应用程序调优 3. 数据库索引优化 4. SQL语句优化 5. 事务处理调 ...
- ssms 缺少索引信息_MySQL3:索引
什么是索引 索引是对数据库表中一列或者多列的值进行排序的一种结构,所引用于快速找出在某个列中有一特定值的行.不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行.表越大,查询数据所花 ...
- [推荐]数据库索引碎片的自动重建或重组
[推荐]数据库索引碎片的自动重建或重组 [推荐]数据库索引碎片的自动重建或重组 --通过知识共享树立个人品牌. 数据库随着使用时间,若不进行相应管理就会越来越慢,优化数据库方法很多,在此不介绍,说 ...
- oracle建索引默认并发,ORACLE重建索引需要考虑问题
一:考虑重建索引的场合 1:表上频繁发生update,delete操作 2:表上发生了alter table ..move操作(move操作导致了rowid变化) 二:判断重建索引的标准 索引重建是否 ...
- mysql为什么要重建索引_MySQL表索引为什么会遭破坏?
此文章主要向大家描述的是MySQL表索引被破坏的问题的产生缘由,以及针对这一问题我们给出其具体的解决方案,下面的文章就是对其相关内容的具体介绍,希望在你今后的学习中会有所帮助. 下午上班,惊闻我的de ...
- mysql索引创建规则、联合与一般索引、执行计划、索引选择,索引重建与下推
数据库索引怎么建,什么时候用到 索引优缺点:为主键外建where子句建立索引可以加速数据库查询,但是索引占用内存,同时update和insert的时候需要同步修改;索引的实现通常使用其变种B+树. 建 ...
- mysql repair 索引_mysql 创建索引、重建索引、查询索引、删除索引 转自:http://www.phpernote.com/mysql/942.html...
本篇文章主要是对MySQL索引操作方法做了一下总结,包括创建索引.重建索引.查询索引.删除索引的操作.以下所列示例中中 `table_name` 表示数据表名,`index_name` 表示索引名,c ...
- 2.Lucene3.6.2包介绍,第一个Lucene案例介绍,查看索引信息的工具lukeall介绍,Luke查看的索引库内容,索引查找过程
1 Lucen目录介绍 2 lucene-core-3.6.2.jar是lucene开发核心jar包 contrib 目录存放,包含一些扩展jar包 3 案例 建立第一个Lucene项目 ...
- 数据库元数据数据字典查询_4_列出给定表的索引信息
列出给定表的索引信息 需求描述 需求:查询出给定的表emp的索引信息. 解决方法:通过各个数据库里提供的与索引相关的数据字典进行查询. 注: 数据库数据集SQL脚本详见如下链接地址 员工表结构和数据初 ...
最新文章
- 如何自学python数据分析-良心整理!学习Python数据分析的正确姿势
- day12装饰器进阶
- linux字符处理工具 新手教程
- 邮箱通知php,PHPMailer 发送邮件(含详细介绍及使用方法说明)
- ejb 2.1 jboss_JBoss AS 8中的Java EE 7和EJB 3.2支持
- 【Pytorch神经网络理论篇】 05 Module类的使用方法+参数Parameters类+定义训练模型的步骤与方法
- GooglePerformanceTools--tcmalloc
- 创建线程时,需要创建的内容
- ubuntu10.4的更新源因过期无法更新的解决方法
- 计算机字符代码表,计算机ASCII码对照表
- 爬虫入门之绘图matplotlib与词云(七)
- J2ME-CLDC/MIDP资源
- 论坛源码手机php,【校园社区APP】带后台完整社区论坛手机应用源码
- C语言bmp转JPEG不用库函数,C++图片格式转换:BMP转JPEG
- logout退出登录该用get方法还是post方法?
- localstorage,sessionstorage,cookie
- 面试时被问有没有别家offer,回答没有,面试总是挂!回答有,就说我是面试选手,欺骗公司!...
- 地铁中计算机网络专业,计算机网络技术在地铁AFC系统中的应用原稿(全文完整版)...
- 浅析安全启动(Secure Boot) —写得很好
- CenOs安装jdk
热门文章
- 解决AndroidStudio更新后在 Building gradle project info 一直卡住
- redhat7图形界面网卡设置_Redhat Linux Interprise基本网络配置与调试
- cdh 安装_使用Cloudera的CDH部署Hadoop:第二步,安装JDK
- 封装element分页组件
- android登录操作代码,Android Studio实现第三方QQ登录操作代码
- axios请求接口http_超级简单好用的 Vue封装axios
- python 中主线程结束 子线程还在运行么_Python爬虫进阶(二)爬虫之多任务模块(Ⅰ)...
- 姓名的首字母组成的图案C语言怎么编,c语言编写一个程序,根据用户输入英文名和姓先显示姓氏,其后跟一个逗号,然后显示名的首字母:...
- turtle库的学习
- Leetcode 581.最短无序连续子数组