sql server 表索引碎片处理
DBCC SHOWCONTIG (Transact-SQL)
更新日期: 2007 年 9 月 15 日
显示指定的表或视图的数据和索引的碎片信息。
重要提示: |
---|
后续版本的 Microsoft SQL Server 将删除该功能。请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。请改用 sys.dm_db_index_physical_stats。 |
Transact-SQL 语法约定
DBCC SHOWCONTIG [ ( { table_name | table_id | view_name | view_id } [ , index_name | index_id ] ) ] [ WITH { [ , [ ALL_INDEXES ] ] [ , [ TABLERESULTS ] ] [ , [ FAST ] ][ , [ ALL_LEVELS ] ] [ NO_INFOMSGS ]}]
- table_name | table_id | view_name | view_id
-
要检查碎片信息的表或视图。如果未指定,则检查当前数据库中的所有表和索引视图。若要获得表或视图 ID,请使用 OBJECT_ID 函数。
- index_name | index_id
-
要检查其碎片信息的索引。如果未指定,则该语句将处理指定表或视图的基本索引。若要获取索引 ID,请使用 sys.indexes 目录视图。
- WITH
-
指定有关 DBCC 语句返回的信息类型的选项。
- FAST
-
指定是否要对索引执行快速扫描和输出最少信息。快速扫描不读取索引的叶级或数据级页。
- ALL_INDEXES
-
显示指定表和视图的所有索引的结果,即使指定了特定索引也是如此。
- TABLERESULTS
-
将结果显示为含附加信息的行集。
- ALL_LEVELS
-
仅为保持向后兼容性而保留。即使指定了 ALL_LEVELS,也只对索引叶级或表数据级进行处理。
- NO_INFOMSGS
-
取消严重级别从 0 到 10 的所有信息性消息。
下表对结果集中的信息进行了说明。
统计信息 | 说明 | |
---|---|---|
扫描页数 |
表或索引中的页数。 |
|
扫描区数 |
表或索引中的区数。 |
|
区切换次数 |
遍历表或索引的页时,DBCC 语句从一个区移动到另一个区的次数。 |
|
每个区的平均页数 |
页链中每个区的页数。 |
|
扫描密度 [最佳计数:实际计数] |
百分比。这是“最佳计数”与“实际计数”的比率。如果所有内容都是连续的,则该值为 100;如果该值小于 100,则存在一些碎片。 “最佳计数”是指在一切都连续链接的情况下,区更改的理想数目。“实际计数”是指区更改的实际次数。 |
|
逻辑扫描碎片 |
扫描索引的叶级页时返回的出错页的百分比。此数与堆无关。对于出错页,分配给索引的下一个物理页不是由当前叶级页中的“下一页”指针所指向的页。 |
|
区扫描碎片 |
扫描索引的叶级页时出错区所占的百分比。此数与堆无关。对于出错区,包含当前索引页的区在物理上不是包含上一个索引页的区的下一个区。
如果索引跨越多个文件,则此数字无意义。
|
|
每页的平均可用字节数 |
扫描的页上平均可用字节数。此数字越大,则页的填充程度越低。如果索引不会有很多随机插入,则数字越小越好。此数字还受行大小影响:行越大,此数字就越大。 |
|
平均密度(全部) |
页的平均密度,以百分比表示。该值会考虑行大小。因此,该值可以更准确地指示页的填充程度。百分比越大越好。 |
如果指定了 table_id 和 FAST,则 DBCC SHOWCONTIG 将返回只包含以下列的结果集。
- 扫描页数
- 区切换次数
- 扫描密度 [最佳计数:实际计数]
- 区扫描碎片
- 逻辑扫描碎片
如果指定了 TABLERESULTS,则 DBCC SHOWCONTIG 将返回以下列以及上一个表中说明的九个列。
统计信息 | 说明 | |
---|---|---|
Object Name |
处理的表或视图的名称。 |
|
ObjectId |
对象名的 ID。 |
|
IndexName |
处理的索引的名称。堆的 IndexName 为 NULL。 |
|
IndexId |
索引的 ID。堆的 IndexId 为 0。 |
|
Level |
索引的级别。级别 0 是索引的叶(或数据)级。 堆的级别为 0。 |
|
页 |
组成某个索引级别或整个堆的页数。 |
|
Rows |
某个索引级别上的数据或索引记录数。对于堆,此值是整个堆中的数据记录数。 对于堆,此函数返回的记录数可能与对该堆运行 SELECT COUNT(*) 返回的行数不匹配。这是因为一行可以包含多条记录。例如,在某些更新的情况下,执行更新操作后单个堆行可能包含一条前推记录和一条被前推记录。另外,大多数大的 LOB 行在 LOB_DATA 存储区中都拆分为多条记录。 |
|
MinimumRecordSize |
某个索引级别或整个堆中的最小记录大小。 |
|
MaximumRecordSize |
某个索引级别或整个堆中的最大记录大小。 |
|
AverageRecordSize |
某个索引级别或整个堆中的平均记录大小。 |
|
ForwardedRecords |
该索引级别或整个堆中的被前推记录数。 |
|
区 |
某个索引级别或整个堆中的区数。 |
|
ExtentSwitches |
遍历表或索引的页时,DBCC 语句从一个区移动到另一个区的次数。 |
|
AverageFreeBytes |
扫描的页上平均可用字节数。此数字越大,则页的填充程度越低。如果索引不会有很多随机插入,则数字越小越好。此数字还受行大小影响:行越大,此数字就越大。 |
|
AveragePageDensity |
页的平均密度,以百分比表示。该值会考虑行大小。因此,该值可以更准确地指示页的填充程度。百分比越大越好。 |
|
ScanDensity |
百分比。这是“最佳计数”与“实际计数”的比率。如果所有内容都是连续的,则该值为 100;如果该值小于 100,则存在一些碎片。 |
|
BestCount |
所有内容连续链接时的区更改理想数量。 |
|
ActualCount |
区更改实际数量。 |
|
LogicalFragmentation |
扫描索引的叶级页时返回的出错页的百分比。此数与堆无关。出错页是指分配给索引的下一个物理页不是由当前叶级页中的“下一页”指针所指向的页。 |
|
ExtentFragmentation |
扫描索引的叶级页时出错区所占的百分比。此数与堆无关。对于出错区,包含当前索引页的区在物理上不是包含上一个索引页的区的下一个区。
如果索引跨越多个文件,则此数字无意义。
|
如果指定了 WITH TABLERESULTS 和 FAST,则结果集将与指定 WITH TABLERESULTS 时一样,但以下列的值将为 null:
Rows |
区 |
MinimumRecordSize |
AverageFreeBytes |
MaximumRecordSize |
AveragePageDensity |
AverageRecordSize |
ExtentFragmentation |
ForwardedRecords |
如果指定了 index_id,则 DBCC SHOWCONTIG 语句将遍历指定索引的叶级上的页链。如果只指定 table_id,或者 index_id 为 0,则将扫描指定表的数据页。该操作仅需要意向共享 (IS) 表锁。通过这种方式,除了需要排他 (X) 表锁的更新和插入以外,可执行所有更新和插入。这就可以根据返回的统计信息数量,实现执行速度与不减少并发之间进行权衡。但是,如果使用此命令只是为了测量碎片,则建议您使用 WITH FAST 选项以优化性能。快速扫描不读取索引的叶级或数据级页。WITH FAST 选项不适用于堆。
SQL Server 2005 中的更改
SQL Server 2005 中计算碎片的算法比 SQL Server 2000 中的算法更精确。因此,碎片值显得更高。例如,在 SQL Server 2000 中,如果一个表的第 11 页和第 13 页在同一区中,而第 12 页不在该区中,则不会将该表视为存在碎片。但是访问这些页需要两次物理 I/O 操作,因此,在 SQL Server 2005 中,将把这种情况算作碎片。
DBCC SHOWCONTIG 不显示数据类型为 ntext、text 和 image 的数据。这是因为 SQL Server 2005 中不再有存储文本和图像数据的文本索引(SQL Server 2000 中的索引 ID 为 255)。有关索引 ID 255 的详细信息,请参阅 sys.sysindexes (Transact-SQL)。
此外,DBCC SHOWCONTIG 也不支持 SQL Server 2005 中的某些新功能。例如:
- 如果指定的表或索引已分区,则 DBCC SHOWCONTIG 只显示指定表或索引的第一个分区。
- DBCC SHOWCONTIG 不显示行溢出存储信息和其他新的行外数据类型,如 nvarchar(max)、varchar(max)、varbinary(max) 和 xml。
SQL Server 2005 中的所有新功能完全由 sys.dm_db_index_physical_stats 动态管理视图支持。
表碎片
DBCC SHOWCONTIG 可确定表是否高度碎片化。在对表进行数据修改(INSERT、UPDATE 和 DELETE 语句)的过程中会出现表碎片现象。由于这些修改通常并不在表的行中平均分布,所以每页的填满状态会随时间而改变。对于扫描部分或全部表的查询,这样的表碎片会导致读取额外的页。从而延缓了数据的并行扫描。
如果索引的碎片非常多,可选择以下方法来减少碎片:
- 删除然后重新创建聚集索引。
重新创建聚集索引将重新组织数据,从而使数据页填满。填充度可以使用 CREATE INDEX 中的 FILLFACTOR 选项进行配置。这种方法的缺点是索引在删除/重新创建周期内为脱机状态,并且该操作是一个整体,不可中断。如果中断索引创建,则不能重新创建索引。 - 对索引的叶级页按逻辑顺序重新排序。
使用 ALTER INDEX…REORGANIZE,对索引的页级页按逻辑顺序重新排序。由于此操作是联机操作,因此语句运行时索引可用。此外,中断该操作不会丢失已完成的工作。这种方法的缺点是在重新组织数据方面没有聚集索引的删除/重新创建操作有效。 - 重新生成索引。
使用 REBUILD 和 ALTER INDEX 重新生成索引。有关详细信息,请参阅 ALTER INDEX (Transact-SQL)。
结果集中的 Avg. Bytes free per page 和 Avg. Page density (full) 统计信息指示索引页的填充度。对于不应具有很多随机插入的索引,Avg. Bytes free per page 数应较低,Avg. Page density (full) 数应较高。使用指定的 FILLFACTOR 选项删除并重建索引可改善统计信息。另外,REORGANIZE 和 ALTER INDEX 可根据其 FILLFACTOR 选项压缩索引,从而改善统计信息。
注意: |
---|
如果索引有很多随机插入和很满的页,则其页拆分数将增加。这将导致更多的碎片。 |
索引的碎片级别可通过以下方式确定:
- 比较“区切换次数”和“扫描区数”的值。
“区切换次数”的值应尽可能接近于“扫描区数”的值。此比率将作为“扫描密度”值计算。此值应尽可能的大,可通过减少索引碎片得到改善。注意: 如果索引涉及多个文件,则此方法无效。 - 了解“逻辑扫描碎片”和“区扫描碎片”的值。
“逻辑扫描碎片”和“区扫描碎片”(对于较小的区)的值是表的碎片级别的最好指标。这两个值应尽可能接近零,但 0% 到 10% 的值都是可接受的。注意: 如果索引涉及多个文件,则“区扫描碎片”的值将较高。若要减小这些值,必须减少索引碎片。
用户必须是表所有者,或者是 sysadmin 固定服务器角色、db_owner 固定数据库角色或 db_ddladmin 固定数据库角色的成员。
A. 显示表的碎片信息
以下示例将显示 Employee
表的碎片信息。
USE AdventureWorks; GO DBCC SHOWCONTIG ("HumanResources.Employee"); GO
B. 使用 OBJECT_ID 获得表 ID,使用 sys.indexes 获得索引 ID
以下示例使用 OBJECT
_ID
和 sys.indexes
目录视图,以获取 AdventureWorks
数据库中 Production.Product
表的 AK_Product_Name
索引的表 ID 和索引 ID。
USE AdventureWorks; GO DECLARE @id int, @indid int SET @id = OBJECT_ID('Production.Product') SELECT @indid = index_id FROM sys.indexes WHERE object_id = @id AND name = 'AK_Product_Name' DBCC SHOWCONTIG (@id, @indid); GO
C. 显示表的简略结果集
以下示例将返回 AdventureWorks
数据库中 Product
表的简略结果集。
USE AdventureWorks; GO DBCC SHOWCONTIG ("Production.Product", 1) WITH FAST; GO
D. 显示数据库中每个表的每个索引的完整结果集
以下示例将显示 AdventureWorks
数据库中每个表的每个索引的完整表结果集。
USE AdventureWorks; GO DBCC SHOWCONTIG WITH TABLERESULTS, ALL_INDEXES; GO
E. 使用 DBCC SHOWCONTIG 和 DBCC INDEXDEFRAG 对数据库中的索引进行碎片整理
以下示例将展示一种简单的方法,对数据库中碎片数量在声明的阈值之上的所有索引进行碎片整理。
/*Perform a 'USE <database name>' to select the database in which to run the script.*/ -- Declare variables SET NOCOUNT ON; DECLARE @tablename varchar(255); DECLARE @execstr varchar(400); DECLARE @objectid int; DECLARE @indexid int; DECLARE @frag decimal; DECLARE @maxfrag decimal;-- Decide on the maximum fragmentation to allow for. SELECT @maxfrag = 30.0;-- Declare a cursor. DECLARE tables CURSOR FORSELECT TABLE_SCHEMA + '.' + TABLE_NAMEFROM INFORMATION_SCHEMA.TABLESWHERE TABLE_TYPE = 'BASE TABLE';-- Create the table. CREATE TABLE #fraglist (ObjectName char(255),ObjectId int,IndexName char(255),IndexId int,Lvl int,CountPages int,CountRows int,MinRecSize int,MaxRecSize int,AvgRecSize int,ForRecCount int,Extents int,ExtentSwitches int,AvgFreeBytes int,AvgPageDensity int,ScanDensity decimal,BestCount int,ActualCount int,LogicalFrag decimal,ExtentFrag decimal);-- Open the cursor. OPEN tables;-- Loop through all the tables in the database. FETCH NEXTFROM tablesINTO @tablename;WHILE @@FETCH_STATUS = 0 BEGIN; -- Do the showcontig of all indexes of the tableINSERT INTO #fraglist EXEC ('DBCC SHOWCONTIG (''' + @tablename + ''') WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS');FETCH NEXTFROM tablesINTO @tablename; END;-- Close and deallocate the cursor. CLOSE tables; DEALLOCATE tables;-- Declare the cursor for the list of indexes to be defragged. DECLARE indexes CURSOR FORSELECT ObjectName, ObjectId, IndexId, LogicalFragFROM #fraglistWHERE LogicalFrag >= @maxfragAND INDEXPROPERTY (ObjectId, IndexName, 'IndexDepth') > 0;-- Open the cursor. OPEN indexes;-- Loop through the indexes. FETCH NEXTFROM indexesINTO @tablename, @objectid, @indexid, @frag;WHILE @@FETCH_STATUS = 0 BEGIN;PRINT 'Executing DBCC INDEXDEFRAG (0, ' + RTRIM(@tablename) + ',' + RTRIM(@indexid) + ') - fragmentation currently '+ RTRIM(CONVERT(varchar(15),@frag)) + '%';SELECT @execstr = 'DBCC INDEXDEFRAG (0, ' + RTRIM(@objectid) + ',' + RTRIM(@indexid) + ')';EXEC (@execstr);FETCH NEXTFROM indexesINTO @tablename, @objectid, @indexid, @frag; END;-- Close and deallocate the cursor. CLOSE indexes; DEALLOCATE indexes;-- Delete the temporary table. DROP TABLE #fraglist; GO
sql server 表索引碎片处理相关推荐
- SQL Server的索引碎片
无论是什么关系型数据库,尤其在OLTP系统中,索引是提升数据访问速度的常用方式之一,但是不同类型的数据库,对索引碎片的处理可能会略有不同. 我们知道,索引碎片多了,意味着可能会扫描更多的数据块.消耗更 ...
- 如何查看SQL Server的索引碎片情况并进行整理
一.查看碎片占用情况 SELECT OBJECT_NAME(ind.OBJECT_ID) AS TableName, ind.name AS IndexName, indexstats.index_t ...
- SQL Server 表分区实战系列(文章索引)
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 前言(Introduction) 实战说明(In Action) 表分区逻辑结构图(Construction) 表分区学 ...
- SQL Server 表和索引存储结构
SQL Server 表和索引存储结构 杜飞 在上一篇文章中,我们介绍了SQL Server数据文件的页面类型,系统通过96个字节的头部信息和系统表从逻辑层面上将表的存储结构管理起来,具体到表的存储结 ...
- 52. SQL Server -- 表分区实战系列(文章索引)
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 前言(Introduction) 实战说明(In Action) 表分区逻辑结构图(Construction) 表分区学 ...
- 理解SQL Server中索引的概念,原理以及其他
简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能.但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索 ...
- T-SQL查询进阶--理解SQL Server中索引的概念,原理以及其他(看了两次了,转了)
简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能.但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索 ...
- sql server 群集_设计有效SQL Server群集索引
sql server 群集 In the previous articles of this series (see bottom for a full index), we described, i ...
- 理解SQL Server中索引的概念,原理
理解SQL Server中索引的概念,原理 摘自:http://51even.iteye.com/blog/1490412 简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索 ...
最新文章
- Spring Cloud(三)服务提供者 Eureka + 服务消费者(rest + Ribbon)
- 使用内存映射文件在进程之间共享数据
- SpringBoot 居然有 44 种应用启动器
- python读写文件代码_Python 读写文件的操作代码
- 一款非常好用的音乐标签及管理工具:Yate for Mac
- 第七讲 塔木德破产分配法练习题
- Go---第六章:方法(小知识点笔记)
- linux hdfs授予文件夹权限,修修改hdfs上的文件所属用户、所属组等读写执行控制权限...
- 计算机房消防设计规范,发电机房消防设计规范要求有哪些
- pwnable.tw---start
- Nakashima Propeller选择Voltaire加速船舶螺旋桨设计
- tableau中文版教程pdf_快速入门Tableau详细教程(
- yum执行出错,There are no enabled repos
- 关键词热度分析工具_不懂亚马逊关键词分析怎么办?10款超好用的亚马逊运营必备关键词研究分析工具,建议收藏!...
- 小小突击队服务器维护多久,《小小突击队》08月06日更新公告
- vs2015安装使用体验
- 2022软件测试工程师的简历怎么写?
- [前端学习笔记1] 前端学习路线
- java电影院购票系统总结_Java实现电影院订票系统代码
- Android apk瘦身讲解