索引碎片检测

索引碎片里我们解释了不同类型的碎片,还有它们如何影响查询性能。在这个文章里,我们会讨论下如何检测索引碎片。

内部碎片检测

内部碎片是关于页面饱和度的一切,可以用DETAILED模式的 sys.dm_db_index_physical_stats,avg_page_space_used_in_percent 列会给出索引的内部碎片,下面的查询会列出超过10个页面,且页面饱和度低于85%的索引。

 1 EXEC sp_configure ‘show advanced options‘, 1
 2 GO
 3 RECONFIGURE WITH OVERRIDE
 4 GO
 5 DECLARE @DefaultFillFactor INT
 6 DECLARE @Fillfactor TABLE
 7     (
 8       Name VARCHAR(100) ,
 9       Minimum INT ,
10       Maximum INT ,
11       config_value INT ,
12       run_value INT
13     )
14 INSERT  INTO @Fillfactor
15         EXEC sp_configure ‘fill factor (%)‘
16 SELECT  @DefaultFillFactor = CASE WHEN run_value = 0 THEN 100
17                                   ELSE run_value
18                              END
19 FROM    @Fillfactor
20
21 SELECT  DB_NAME() AS DBname ,
22         QUOTENAME(s.name) AS CchemaName ,
23         QUOTENAME(o.name) AS TableName ,
24         i.name AS IndexName ,
25         stats.Index_type_desc AS IndexType ,
26         stats.page_count AS [PageCount] ,
27         stats.partition_number AS PartitionNumber ,
28         CASE WHEN i.fill_factor > 0 THEN i.fill_factor
29              ELSE @DefaultFillFactor
30         END AS [Fill Factor] ,
31         stats.avg_page_space_used_in_percent ,
32         CASE WHEN stats.index_level = 0 THEN ‘Leaf Level‘
33              ELSE ‘Nonleaf Level‘
34         END AS IndexLevel
35 FROM    sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, ‘DETAILED‘)
36         AS stats ,
37         sys.objects AS o ,
38         sys.schemas AS s ,
39         sys.indexes AS i
40 WHERE   o.OBJECT_ID = stats.OBJECT_ID
41         AND s.schema_id = o.schema_id
42         AND i.OBJECT_ID = stats.OBJECT_ID
43         AND i.index_id = stats.index_id
44         AND stats.avg_page_space_used_in_percent <= 85
45         AND stats.page_count >= 10
46         AND stats.index_id > 0
47 ORDER BY stats.avg_page_space_used_in_percent ASC ,
48         stats.page_count DESC

这里我在WHERE条件里指定了只列出超过10页,且页面饱和度低于85%的结果。这是基于我当前系统环境和一些文档的最佳实践。avg_page_space_used_in_percent 的低值,加上PageCount 的高值,会影响到系统性能。avg_page_space_used_in_percent 的低值会下列不同的原因:

  • 分页和记录删除:在这个情况下,我们需要对索引进行REBUILD和REORGANIZE操作。如果碎片报告在非页层,需要REBUILD来减少碎片。
  • 填充因子设置:索引填充因子值的错误设置可能造成内部碎片。如果内部碎片是因为填充因子设置造成的,我们需要使用填充因子的新值对索引进行REBUILD。
  • 记录大小:有些时候,记录大小也会称为内部碎片的原因。例如我们假设一条记录大小是3000 bytes,一页只能保存2条记录。第3条记录不能插入页,因为页里剩下的空间小于3000 bytes。在这种情况下,每一页都会有2060 bytes的空余。为了解决因这个原因造成的碎片,我们需要重新设计表或者对表进行垂直分区。

外部碎片检测

外部检测也是用LIMITED模式的sys.dm_db_index_physical_stats,但我们使用avg_fragmentation_in_percent 的结果来检测外部碎片。使用LIMITED模式会给我们叶子层的碎片。如果要获得非页层的碎片,可以使用DETAILED或SAMPLE模式。碎片是页的连续分配。例如如果一个索引有150页,页分配从1到50,55到60,65到120,还有140到180。每个这样序列被称为碎片,这里就是有4个碎片。

 1 EXEC sp_configure ‘show advanced options‘, 1
 2 GO
 3 RECONFIGURE WITH OVERRIDE
 4 GO
 5 DECLARE @DefaultFillFactor INT
 6 DECLARE @Fillfactor TABLE
 7     (
 8       Name VARCHAR(100) ,
 9       Minimum INT ,
10       Maximum INT ,
11       config_value INT ,
12       run_value INT
13     )
14 INSERT  INTO @Fillfactor
15         EXEC sp_configure ‘fill factor (%)‘
16 SELECT  @DefaultFillFactor = CASE WHEN run_value = 0 THEN 100
17                                   ELSE run_value
18                              END
19 FROM    @Fillfactor
20
21 SELECT  DB_NAME() AS DBname ,
22         QUOTENAME(s.name) AS CchemaName ,
23         QUOTENAME(o.name) AS TableName ,
24         i.name AS IndexName ,
25         stats.Index_type_desc AS IndexType ,
26         stats.page_count AS [PageCount] ,
27         stats.partition_number AS PartitionNumber ,
28         CASE WHEN i.fill_factor > 0 THEN i.fill_factor
29              ELSE @DefaultFillFactor
30         END AS [Fill Factor] ,
31         stats.avg_fragmentation_in_percent ,
32         stats.fragment_count ,
33         CASE WHEN stats.index_level = 0 THEN ‘Leaf Level‘
34              ELSE ‘Nonleaf Level‘
35         END AS IndexLevel
36 FROM    sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, ‘LIMITED‘)
37         AS stats ,
38         sys.objects AS o ,
39         sys.schemas AS s ,
40         sys.indexes AS i
41 WHERE   o.OBJECT_ID = stats.OBJECT_ID
42         AND s.schema_id = o.schema_id
43         AND i.OBJECT_ID = stats.OBJECT_ID
44         AND i.index_id = stats.index_id
45         AND stats.avg_fragmentation_in_percent >= 20
46         AND stats.page_count >= 1000
47 ORDER BY stats.avg_fragmentation_in_percent DESC ,
48         stats.page_count DESC

在这个查询里,我使用的WHERE条件只列出碎片大于20%且最少1000页的索引。avg_fragmentation_in_percent 值高的话,可能有下列原因:

  • SQL Server存储引擎对表或索引从混合区开始分配页,直到页数达到8页。一旦页数达到8页,SQL Server引擎开始把整个统一区分配给索引。因此这里对于小表会有很高的碎片,重建索引会增加碎片。例如,我们假设一个索引有7页,这些页是从2个混合区分配的,当我们重建索引的时候,很可能把页分配从2个混合区变成最大7个混合区,这就导致了碎片增加。
  • 即使也从混合区分配,还是有碎片产生的可能。当索引大小增长时,在非页层也需要更多的页。如果分配给叶子层的最后页是250,在叶子层索引结构里增加更多的记录,可能会在第1层索引需要更多的页,然后SQL Server存储引擎分配251页在第1层索引,这就在叶子层产生了碎片。
  • 造成分页的其他常见原因就是DML操作。Rebuild/Reorganize 索引对于上述不能很好的减少碎片,但可以减少由分页或删除操作造成的碎片。
  • 我们按下列要求进行索引的维护:
    • 20-40%的碎片,用Reorganize来重新组织索引。
    • 大于40%的碎片,需要用Rebuild来重建索引。
    • 低于1000页的索引,在索引维护逻辑上是被忽略的(不处理)
    • 大于50k的页,碎片在10-20%之间,也要用Reorganize来重新组织索引。
时间: 2024-10-12 14:51:54

索引碎片检测的相关文章

索引碎片检测和整理

在实现数据查找时,对无序数据进行查找,最快的查找算法是哈希查找,对有序数据进行查找,最快的查找算法是平衡树查找.在传统的关系型数据库中,聚集索引和非聚集索引都是平衡树类型的存储结构,用于顺序存储数据,便于对数据进行快速的平衡树查找.索引结构是BTree结构,分为叶子节点和非叶子节点,叶子节点用于存储数据,而非叶子节点(中间节点和根节点)用于存储索引键,节点数据按照索引键排序.理论上,一旦数据集确定下来,索引查找的时间消耗就只跟索引结构的层次有关系,层次越多,查找消耗的时间越多,而碎片会影响索引的

检测和整理索引碎片

索引碎片的检测和整理 存储数据是为了查找数据,存储结构影响数据查找的性能.对无序数据进行查找,最快的查找算法是哈希查找:对有序数据进行查找,最快的查找算法是平衡树查找.在传统的关系型数据库中,聚集索引和非聚集索引都是平衡树(B-Tree)类型的存储结构,用于顺序存储数据,便于实现数据的快速查找.除了提升数据查找的性能之外,索引还能减少硬盘IO和内存消耗.通常情况下,硬盘IO是查找性能的瓶颈,由于索引是数据表的列的子集,这意味着,索引只存储部分列的数据,占用的硬盘空间比全部列少了很多,因此,数据库

索引碎片的检测和整理

存储数据是为了查找数据,存储结构影响数据查找的性能.对无序数据进行查找,最快的查找算法是哈希查找:对有序数据进行查找,最快的查找算法是平衡树查找.在传统的关系型数据库中,聚集索引和非聚集索引都是平衡树(B-Tree)类型的存储结构,用于顺序存储数据,便于实现数据的快速查找.除了提升数据查找的性能之外,索引还能减少硬盘IO和内存消耗.通常情况下,硬盘IO是查找性能的瓶颈,由于索引是数据表的列的子集,这意味着,索引只存储部分列的数据,占用的硬盘空间比全部列少了很多,因此,数据库引擎只需要消耗相对较少

索引碎片整理(转)

索引碎片整理 一碎片种类 1 内部碎片,又称为平均页密度.是指索引正在占有超过它实际所需的空间大小. 它具有两面型:低百分比会对读取数据的查询产生负面影响,会涉及更多读取操作,因为如果页被填充满的话, 只需读取更少的页:另一方面,如果如果在创建索引时设置一个较低的填充因子,就可以避免当插入更多记录而不 必进行页拆分. 对应sys.dm_db_index_physical_stats的列avg_page_space_used_in_percent. 2 外部碎片,又称平均碎片百分比,或逻辑碎片.是

41.oracle索引,分析索引,索引碎片整理

概述 索引分为B树索引和位图索引.我们主要研究B树索引,B树索引如下图(图片源自网络): 索引是与表相关的一个可选结构,在逻辑上和物理上都独立于表数据,索引能优化查询,不能优化DML,oracle自动维护索引,频繁的DML操作反而会赢钱大量的索引卫华. 如果sql语句仅仅访问被索引的列,那么数据库只需从索引中读取数据,而不会读取表:如果该语句还要访问未被索引的列,那么数据库会使用rowid来查找表中的行,通常,为检索表数据,数据库以交换方式先读取索引块,然后读取对应的表. 索引的目的是减少IO

SQL Server2005索引碎片分析和解决方法

SQL Server2005索引碎片分析和解决方法 本文作者(郑贤娴),请您在阅读本文时尊重作者版权. 摘要: SQL Server,为了反应数据的更新,需要维护表上的索引,因而这些索引会形成碎片.根据工作量的特征,这些碎片会影响对应的工作性能.此文帮助决定是否需要整理碎片以改善性能的信息.SQL Serve提供一些命令来实现索引的碎片整理.这里比较其中两个命令:DBCC DBREINDEX 和 DBCC INDEXDEFRAG. 关键词: SQL Server;索引碎片;数据库优化毫无疑问,给

SQL Server索引的维护 - 索引碎片、填充因子 &lt;第三篇&gt;

实际上,索引的维护主要包括以下两个方面: 页拆分 碎片 这两个问题都和页密度有关,虽然两者的表现形式在本质上有所区别,但是故障排除工具是一样的,因为处理是相同的. 对于非常小的表(比64KB小得多),一个区中的页面可能属于多余一个的索引或表---这被称为混合区.如果数据库中有太多的小表,混合区帮助SQL Server节约磁盘空间. 随着表(或索引)增长并且请求超过8个页面,SQL Server创建专用于该表(或索引)的区并且从该区中分配页面.这样一个区被称为统一区,它可以为多达8个相同表或索引的

Oracle索引碎片检查及定期重建常用表的索引

转载地址:http://www.cnblogs.com/zhaoguan_wang/p/5169821.html 背景说明: 今天查阅书籍时,偶然间发现"在对某个索引行执行删除操作时,只是为该行增加了一个删除标记,这个索引行并不会释放它的存储空间,Insert产生的新的索引行也不能被插入到该位置.索引列的修改过程其实是将对应的列值删除,然后再插入新的列值(与数据行本身的修改是不一致的,这也正是我们尽量不使用修改频繁的列来创建索引的原因).所以,无论是插入.修改.删除,都需要消耗存储空间,增大B-

SqlServer索引碎片

1.产生碎片的操作 通过sys.dm_index_physical_stats来查看,索引上的页不在具有连续性时就会产生碎片,碎片是索引上页拆分的物理结果. (1).插入操作: INSERT操作在聚集索引和非聚集索引上都可以引起碎片 使用业务键或者GUID等类型 做聚集索引,很容易产生碎片 代码如下: IF OBJECT_ID('dbo.Table_GUID') IS NOT NULL DROP TABLE dbo.Table_GUID; CREATE TABLE Table_GUID ( Ro