Transact-SQL 参考

DBCC SHOWCONTIG

显示指定的表的数据和索引的碎片信息。

语法

DBCC SHOWCONTIG
    [    ( { table_name | table_id | view_name | view_id }
            [ , index_name | index_id ]
        )
    
]
    [ WITH { ALL_INDEXES
                | FAST [ , ALL_INDEXES ]
                | TABLERESULTS [ , { ALL_INDEXES } ]
                [ , { FAST | ALL_LEVELS } ]
            }
    ]

参数

table_name | table_id | view_name | view_id

是要对其碎片信息进行检查的表或视图。如果未指定,则对当前数据库中的所有表和索引视图进行检查。若要获得表或视图 ID,请使用 OBJECT_ID 函数。

index_name | index_id

是要对其碎片信息进行检查的索引。如果未指定,则该语句对指定表或视图的基索引进行处理。若要获得索引 ID,请使用 sysindexes

WITH

指定由 DBCC 语句所返回的信息类型选项。

FAST

指定是否要对索引执行快速扫描和输出最少信息。快速扫描不读取索引的叶或数据级页。

TABLERESULTS

将结果显示为带有附加信息的行集。

ALL_INDEXES

显示指定表和视图的所有索引的结果(即使指定特定的索引)。

ALL_LEVELS

只能与 TABLERESULTS 选项一起使用。不能与 FAST 选项一起使用。指定是否为所处理的每个索引的每个级别产生输出。如果未指定,将只对索引叶级或表数据级进行处理。

注释

当指定 index_id 时,DBCC SHOWCONTIG 语句将遍历指定索引的叶级上的页链。如果只指定 table_id,或者如果 index_id 为 0,则对指定表的数据页进行扫描。

DBCC SHOWCONTIG 确定表是否高度碎片化。在对表进行数据修改(INSERT、UPDATE 和 DELETE 语句)的过程中会出现表碎片现象。由于这些修改通常并不在表的行中进行平均分布,所以每页的填满状态会随时间而改变。对于扫描部分或全部表的查询,这些表碎片会导致额外的页读取,这将防碍数据的并行扫描。

当索引的碎片非常多时,有两种减少碎片的方法:

结果集中的"每页上的平均可用字节数"和"平均页密度(完整)"统计量指出索引页的饱满程度。"每页上的平均可用字节数"的数字应较小,而"平均页密度(完整)"的数字应较大。在指定 FILLFACTOR 选项的情况下除去和重新创建聚集索引可改善这些统计。另外,DBCC INDEXDEFRAG 命令在压缩索引时考虑其 FILLFACTOR,这将改善这些统计。

索引的碎片级可以两种方式确定:

结果集

下表描述结果集内的信息。

统计 描述
扫描页数 表或索引的页数。
扫描扩展盘区数 表或索引中的扩展盘区数。
扩展盘区开关数 遍历索引或表的页时,DBCC 语句从一个扩展盘区移动到其它扩展盘区的次数。
平均扩展盘区上的平均页数 页链中每个扩展盘区的页数。
扫描密度
[最佳值:实际值]
最佳值是指在一切都连续地链接的情况下,扩展盘区更改的理想数目。实际值是指扩展盘区更改的实际次数。如果一切都连续,则扫描密度数为 100;如果小于 100,则存在碎片。扫描密度为百分比值。
逻辑扫描碎片 对索引的叶级页扫描所返回的无序页的百分比。该数与堆集和文本索引无关。无序页是指在 IAM 中所指示的下一页不同于由叶级页中的下一页指针所指向的页。
扩展盘区扫描碎片 无序扩展盘区在扫描索引叶级页中所占的百分比。该数与堆集无关。无序扩展盘区是指:含有索引的当前页的扩展盘区不是物理上的含有索引的前一页的扩展盘区后的下一个扩展盘区。
平均每页上的平均可用字节数 所扫描的页上的平均可用字节数。数字越大,页的填满程度越低。数字越小越好。该数还受行大小影响:行大小越大,数字就越大。
平均页密度(完整) 平均页密度(为百分比)。该值考虑行大小,所以它是页的填满程度的更准确表示。百分比越大越好。

如果指定表 ID 和 FAST 选项,DBCC SHOWCONTIG 将返回仅包含以下列的结果集:

如果指定 TABLERESULTS,DBCC SHOWCONTIG 将返回在第一个表中描述的 8 列和以下的附加列。

统计 描述
ObjectName 处理的表或视图的名称。
ObjectId 对象名 ID。
IndexName 处理的索引名。堆集的 IndexName 为 NULL。
IndexId 索引的 ID。堆集的 IndexId 为 0。
Level 索引的级别。级别 0 是索引的叶(或数据)级。级别数随着沿树向上移动到索引根而增加。堆集的级别为 0。
Pages 组成某个索引级或整个堆集的页数。
Rows 某个索引级上的数据或索引记录数。对于堆集,这是整个堆集中的数据记录数。
MinimumRecordSize 某个索引级或整个堆集中的最小记录大小。
MaximumRecordSize 某个索引级或整个堆集中的最大记录大小。
AverageRecordSize 某个索引级或整个堆集中的平均记录大小。
ForwardedRecords 某个索引级或整个堆集中的转发记录数。
Extents 某个索引级或整个堆集中的扩展盘区数。

指定 TABLERESULTS 和 FAST 时,DBCC SHOWCONTIG 将返回如下列。

权限

DBCC SHOWCONTIG 权限默认授予 sysadmin 固定服务器角色或 db_owner db_ddladmin 固定数据库角色的成员以及表的所有者且不可转让。

示例
A. 显示表的碎片信息

下例显示带指定表名的表的碎片信息。

USE Northwind
GO
DBCC SHOWCONTIG (Employees)
GO
B. 使用 OBJECT_ID 获得表 ID 和使用 sysindexes 获得索引 ID

下例使用 OBJECT_ID 和 sysindexes 获得 authors 表的 aunmind 索引的表 ID 和索引 ID。

USE pubs
GO
DECLARE @id int, @indid int
SET @id = OBJECT_ID('authors')
SELECT @indid = indid 
FROM sysindexes
WHERE id = @id 
   AND name = 'aunmind'
DBCC SHOWCONTIG (@id, @indid)
GO
C. 显示表的简略结果集

下例返回 pubs 数据库中 authors 表的简略结果集。

USE pubs
DBCC SHOWCONTIG ('authors', 1) WITH FAST
D. 显示数据库中每个表上的每个索引的完整结果集

下例显示 pubs 数据库中每个表上的每个索引的完整表结果集。

USE pubs
DBCC SHOWCONTIG WITH TABLERESULTS, ALL_INDEXES
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 (128)
DECLARE @execstr   VARCHAR (255)
DECLARE @objectid  INT
DECLARE @indexid   INT
DECLARE @frag      DECIMAL
DECLARE @maxfrag   DECIMAL

-- Decide on the maximum fragmentation to allow
SELECT @maxfrag = 30.0

-- Declare cursor
DECLARE tables CURSOR FOR
   SELECT TABLE_NAME
   FROM INFORMATION_SCHEMA.TABLES
   WHERE 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 NEXT
   FROM tables
   INTO @tablename

WHILE @@FETCH_STATUS = 0
BEGIN
-- Do the showcontig of all indexes of the table
   INSERT INTO #fraglist 
   EXEC ('DBCC SHOWCONTIG (''' + @tablename + ''') 
      WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS')
   FETCH NEXT
      FROM tables
      INTO @tablename
END

-- Close and deallocate the cursor
CLOSE tables
DEALLOCATE tables

-- Declare cursor for list of indexes to be defragged
DECLARE indexes CURSOR FOR
   SELECT ObjectName, ObjectId, IndexId, LogicalFrag
   FROM #fraglist
   WHERE LogicalFrag >= @maxfrag
      AND INDEXPROPERTY (ObjectId, IndexName, 'IndexDepth') > 0

-- Open the cursor
OPEN indexes

-- loop through the indexes
FETCH NEXT
   FROM indexes
   INTO @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 NEXT
      FROM indexes
      INTO @tablename, @objectid, @indexid, @frag
END

-- Close and deallocate the cursor
CLOSE indexes
DEALLOCATE indexes

-- Delete the temporary table
DROP TABLE #fraglist
GO

请参见

CREATE INDEX

DBCC

DBCC DBREINDEX

DBCC INDEXDEFRAG

DROP INDEX

OBJECT_ID

空间分配和重新使用

sysindexes

表和索引构架