2013-02-25 22 views
0

我有一个二进制(128)列的表。我在Varbinary(128)上选择了二进制(128),所以它会保留所有128个字节,并在更新二进制值时防止页面拆分。出于测试目的,我的索引中有一个100的FILLFACTOR。由更新到二进制(128)导致的页面拆分列

我发现,即使将列设置为二进制(128)值,在对此列执行更新时仍然会导致页面拆分。

任何人有任何想法为什么?

下面是一些代码来测试...

--  Create working dataset 
Create Table TestTable (tID Int Identity, TestBinary Binary(128)); 
Create Clustered Index hmmmm On TestTable (TestBinary) With (FillFactor=100); 

With recur As 
( 
     Select Convert(Binary(128),0x01) As val, 1 As incr 
     Union All 
     Select Convert(Binary(128),incr + 0x01), incr + 1 
     From recur 
     Where incr < 100 
) 
Insert TestTable (TestBinary) 
Select Convert(Binary(128),Convert(Int,r.val) + Convert(Int,r2.val) + Convert(Int,r3.val)) As TestBinary 
From recur r 
Cross Join recur r2 
Cross Join recur r3; 

--  Rebuild Index as needed while testing 
Alter Index [hmmmm] On [dbo].[TestTable] Rebuild 

--  Check index fragmentation 
SELECT Db_Name() As DatabaseName, 
     o.id, 
     s.name, 
     o.name, 
     page_count, 
     record_count, 
     index_type_desc, 
     index_id, 
     index_depth, 
     index_level, 
     avg_fragmentation_in_percent, 
     fragment_count, 
     avg_fragment_size_in_pages, 
     avg_page_space_used_in_percent 
From sys.dm_db_index_physical_stats (DB_ID(), Object_ID('dbo.TestTable'), NULL , NULL, 'Detailed') n 
Join sysobjects o 
     On n.object_id = o.id 
Join sys.schemas s 
     On o.uid = s.schema_id; 

--  Update the records 
Update t 
Set  TestBinary = Convert(Binary(128),(Convert(Int,TestBinary) + 10000)) 
From TestTable t 

如果在100它会导致严重的碎片化FILLFACTOR进行大的更新,但如果我必须在90一切FILLFACTOR好。我以为非var数据类型应该保留内存,所以你不会遇到这个问题。存储通货膨胀从哪里来?

谢谢!

回答

3

它可能不是通货膨胀,而是移动。由于您在二进制(128)列上创建了聚簇索引,因此数据将根据该值进行排序。

当您更新该值时,物理记录可能必须存储在另一页上以维护订单。如果其他页面已满,则必须将其拆分。

+0

Upvoting,因为这是一个很好的电话,绝对正确。我从更新中删除了“Where tID%10 = 0”,而是更新了所有记录。这应该保持顺序,正确吗?这仍然会导致碎片化。 – 2013-02-25 22:06:26

+0

最后,是的,它会维持秩序。然而,虽然这是一个批处理操作,但每个记录最终都必须在物理层面逐一更新。每条记录更新后,它将被移动到正确的位置。因此,第一个记录将不得不拆分页面。下一个可能会转到新拆分的页面,但最终会再次打满整个页面,并最终导致另一个页面拆分。 – 2013-02-25 22:36:07

+0

最后澄清问题,然后我接受答案。如果我没有标识列,而是将Varchar作为主键/聚集索引,那么Binary(128)记录的更改是否会导致聚集索引发生更改,从而导致页面拆分?与聚集索引相关联的包含表数据的更改是否会导致这种情况,或者因为它们都是二进制(128)值,这些新数据是否会完全替代旧数据? – 2013-02-25 22:57:49