sql server 表索引碎片处理
DBCC SHOWCONTIG (Transact-SQL)
更新日期: 2007 年 9 月 15 日
显示指定的表或视图的数据和索引的碎片信息。
重要提示: |
---|
后续版本的 Microsoft SQL Server 将删除该功能。请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。请改用 sys.dm_db_index_physical_stats。 |
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(*) |
|
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 FOR
SELECT TABLE_SCHEMA + '.' + 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 the cursor for the 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
sql server 表索引碎片处理的更多相关文章
- [转]SQL SERVER整理索引碎片测试
SQL SERVER整理索引碎片测试 SQL SERVER整理索引的方法也就这么几种,而且老是自作聪明的加入智能判断很不爽,还是比DBMS_ADVISOR差远了: 1SQL SERVER 2000/2 ...
- sql server 查看索引碎片大小,并定期重建索引
查看碎片情况使用 dbcc showcontig 函数来进行 代码: --改成当前库 use DB_Name --创建变量 指定要查看的表 declare @table_id int set @ ...
- 改进SQL Server 性能 - 索引碎片重建
我们先来看一个用户表上的索引碎片情况: DBCC SHOWCONTIG scanning 'Lead' table...Table: 'Lead' (1422628111); index ID: 1, ...
- SQL Server清理索引碎片
DECLARE @SchemeName NVARCHAR(MAX)=N''; DECLARE @TableName NVARCHAR(MAX)=N''; DECLARE @IndexName NVAR ...
- SQL server 表中如何创建索引?
SQL server 表中如何创建索引?看个示例,你就会了 use master goif db_id(N'zhangxu')is not nulldrop database zhangxugocre ...
- 理解SQL Server中索引的概念
T-SQL查询进阶--理解SQL Server中索引的概念,原理以及其他 简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能 ...
- T-SQL查询进阶--理解SQL Server中索引的概念,原理以及其他
简介 在SQL Server中,索引是一种增强式的存在,这意味着,即使没有索引,SQL Server仍然可以实现应有的功能.但索引可以在大多数情况下大大提升查询性能,在OLAP中尤其明显.要完全理解索 ...
- 理解SQL Server中索引的概念,原理
转自:http://www.cnblogs.com/CareySon/archive/2011/12/22/2297568.html 简介 在SQL Server中,索引是一种增强式的存在,这意味着, ...
- SQL Server 查询优化 索引的结构与分类
一.索引的结构 关系型数据库中以二维表来表达关系模型,表中的数据以页的形式存储在磁盘上,在SQL SERVER中,数据页是磁盘上8k的连续空间,那么,一个表的所有数据页在磁盘上是如何组织的呢?分两种情 ...
随机推荐
- Android动画效果animation
1.Tween 根据指定动画开始和结束时的对象属性(位置.Alpha值(透明度).大小.角度等)以及动画播放的时间长度生成动画: 2.Frame 指定每一帧所播放的图片和时间长度. 建立动画的方法 ...
- HDU - 4965 Fast Matrix Calculation 【矩阵快速幂】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4965 题意 给出两个矩阵 一个A: n * k 一个B: k * n C = A * B M = (A ...
- 动态创建selectjs 操作select和option
1.动态创建select function createSelect(){ var mySelect = document.createElement("select"); myS ...
- 从mysqldump整库备份文件中恢复单表
最近,系统更新出现了问题,比较紧急,需要对三张表进行回档.由于我们都是采用mysqldump进行每天全备整库,数据量比较大,一个备份文件大概有70G,需要从这个70G文件中恢复三张表,真是蛋疼至极啊, ...
- P3214 [HNOI2011]卡农
题目 P3214 [HNOI2011]卡农 在被一题容斥\(dp\)完虐之后,打算做一做集合容斥这类的题了 第一次深感HNOI的毒瘤(题做得太少了!!) 做法 求\([1,n]\)组成的集合中选\(m ...
- Spark Structured Streaming框架(5)之进程管理
Structured Streaming提供一些API来管理Streaming对象.用户可以通过这些API来手动管理已经启动的Streaming,保证在系统中的Streaming有序执行. 1. St ...
- 【Linux不需要磁盘碎片整理的真正原因是因为Linux只是一个内核,它没有磁盘可以整理】
[Linux不需要磁盘碎片整理的真正原因是因为Linux只是一个内核,它没有磁盘可以整理]
- 算法(Algorithms)第4版 练习 2.2.10
关键代码实现: private static void merge(Comparable[] input, int lo, int mid, int hi) { //copy input[lo,mid ...
- 关于 haproxy keepalived的测试
可以阅读的一篇文章(http://blog.csdn.net/xyang81/article/details/52554398) 以下测试的配置都是基本的,简单化的,达到了效果滴,没有参考上面文档 准 ...
- python_unittest详解
一 整体结构概览 unittest原名为PyUnit,是由java的JUnit衍生而来.对于单元测试,需要设置预先条件,对比预期结果和实际结果. 整体结构:unittest库提供了test cases ...