Answers:
碎片在堆中意味着什么
您avg_fragmentation_in_percent
通过查询sys.dm_db_index_physical_stats
DMV 从列中获得的堆中的碎片值指出:
索引的逻辑碎片,或IN_ROW_DATA分配单元中的堆的扩展碎片。
此外,同一BOL表示
这是堆的叶子页面中乱序扩展的百分比。乱序范围是指包含堆的当前页面的范围实际上不是包含上一页的范围之后的下一个范围的范围。
因此,您可以看到,分配给堆的页面不是存在的可用空间,而是造成碎片的页面顺序的变化。
这可以通过小测试来证明。让我们创建一个堆表并在其中插入一些记录,然后检查碎片。
create table dbo.HeapTest
(
Id INT not NULL Default (1),
Col1 char(5000) Not null Default ('Heaps Are Cool')
)
SET NOCOUNT ON
Insert into dbo.Heaptest default values
go 50
select index_type_desc,avg_fragmentation_in_percent,fragment_count,
avg_page_space_used_in_percent,record_count
from sys.dm_db_index_physical_stats(db_id(),object_id('dbo.HeapTest','U'),0,default,'detailed')
因此,将在其中创建带有50条记录的堆表。以下是查询DMV sys.dm_db_index_physical统计信息后的碎片情况
您可以看到avg_fragmentation_in_percent
列值为33%。现在让我们看看页面的排列方式。这可以通过使用未记录的查询来完成%%lockres%%
。该查询将是
SELECT %%lockres%%, * FROM dbo.HeapTest;
下面是输出的样子。仅附上它的相关部分。由于我们在dbo.HeapTest表中插入了50行,因此该查询产生了50行。
它说的是第一页具有ID 197
,下一页具有ID,242
随后的页面具有连续的ID,直到我们到达页面ID为止,264
因为在此之后我们得到页面ID 280
。因此,页面ID号的这种跳跃实际上是导致碎片的原因。
现在,以免重建堆并再次运行该命令以查看碎片和页面排列方式。我们会像
您可以看到碎片化了14%
。
让我们看看分配的页码
我们只有一个跳转点,所有页面都按顺序分配了页面ID。由于仅一跳碎片就大大减少了。
我再次重建了堆,现在当我检查碎片时,它完全消失了。和页面ID分配就像
为什么碎片增加
现在,关于可能导致碎片增加的原因,我们可以证实这一事实:当页面被分配给堆时,它们将不是连续的,正如您所见,导致碎片增加的原因是分配给页面的PAGE ID的跳跃。
在脑后,您还应记住,HEAP的碎片一词没有任何含义,您将如何为一堆无序页面定义碎片。
真的担心碎片
如果确实遇到堆表碎片化且查询变慢的情况,那么在表上创建聚集索引比重建它更好。原因是当您重建堆时,所有基础非索引索引也会被重建,从而导致重建过程花费更长的时间,这会占用大量资源并膨胀事务日志。在生产系统上,人们总是会尝试避免这种情况。保罗在他关于堆的神话部分对此进行了论述。
PS:请不要在生产系统上使用未记录的命令。这只是为了演示。
Heaptest
并给出结果。我确定您可能错过了一些东西。只要确保兼容性级别不是80,在这种情况下db_id函数就无法正常工作