性能優化與故障排除百日談(16)-索引的維護-設置填充因子-誤區解析


性能優化故障排除百日談(16)-索引的維護-設置填充因子-誤區解析

我們在之前的文章中已經多次提到了“填充因子”,並且在上一篇文章談到索引碎片的時候,也知道了填充因子的重要性。盡管如此,其實我們很多的時候在建立索引,維護索引的時候並沒有對填充因子過於太多的關注。



我們本文就來說說填充因子的話題。



在討論之前,首先要聲明一下:如何要比較合理的設置填充因子,一定要知道表中的數據的使用情況,還有索引所在列的類型和特性(如是否是采用GUID,還是Identity自增,還是采用其他的生成方式)。沒有一個一蹴而就,完美的方案,一切都是隨着情況而變化的,但是分析的思路是不變的,切記



關於填充因子的概念我們這里不做太多的討論,我們就來討論幾種需要關注填充因子的情況,同時也看看有關填充因子的一些誤區。

 

 

填充因子的誤區


 

以為填充因子是使用在數據插入的時候使用
 

這個誤區可能是很多人所犯的,因為我們知道,所謂的填充因子,就是在確定頁上面到底有多大的空間被填充,或者換句話說,也確定頁上面有多少空白被保留。那么,這個保留的空間就是為了防止我們在索引頁中插入新數據的時候發生不必要的也拆分,從而減少碎片,從而節省資源,提升性能。


 

相信很多的朋友都按照所講述的進行理解的,其實這是有問題的。為了使得大家更加清楚的認識這個問題,我們通過一個例子來說明下。
 

在下面的示例中,我們將會一個表AgileSharp_FillFactorDemo上面建立一個聚集索引,這個索引的填充因子是50%。並且在數據表建立好了之后我,我們會插入一些數據進去,然后我們通過查看sys.dm_db_index_physical_stats這個動態管理函數來看看索引頁中的空間的使用情況。

CREATE  TABLE dbo.AgileSharp_FillFactorDemo
(
RowID  int  NOT  NULL
,Column1  varchar( 500)
);

ALTER  TABLE dbo.AgileSharp_FillFactorDemo  ADD  CONSTRAINT
PK_AgileSharp_FillFactorDemo  PRIMARY  KEY  CLUSTERED (RowID)  WITH( FILLFACTOR  =  50);

WITH L1(z)  AS ( SELECT  0  UNION  ALL  SELECT  0)
, L2(z)  AS ( SELECT  0  FROM L1 a  CROSS  JOIN L1 b)
, L3(z)  AS ( SELECT  0  FROM L2 a  CROSS  JOIN L2 b)
, L4(z)  AS ( SELECT  0  FROM L3 a  CROSS  JOIN L3 b)
, L5(z)  AS ( SELECT  0  FROM L4 a  CROSS  JOIN L4 b)
, L6(z)  AS ( SELECT  TOP  1000  0  FROM L5 a  CROSS  JOIN L5 b)

INSERT  INTO dbo.AgileSharp_FillFactorDemo
SELECT ROW_NUMBER()  OVER ( ORDER  BY z)  AS RowID,  REPLICATE( ' X '500)
FROM L6

然后運行下面的查詢:

 

SELECT  object_id, index_id, avg_page_space_used_in_percent
FROM sys.dm_db_index_physical_stats( DB_ID(), OBJECT_ID( ' dbo.AgileSharp_FillFactorDemo '), NULL, NULL, ' DETAILED ')
WHERE index_level  =  0

 

 

結果如下:


 

相信看到結果的朋友會非常吃驚:為什么填充因子沒有起到預想的作用



 

這個結果之所以沒有按照大家的想法,是因為我們的理解有誤。


 

其實,填充因子一開始不會在數據修改的過程中使用,而是在索引重建,重組和創建的時候使用。換句話說,就是在創建了索引,設置了填充因子之后,填充因子不會按照我們的期望發生作用,直到我們第一次重組或者重建了索引之后,此時填充因子才會起作用,而且后續的數據的修改(Insert,Update,Delete)才會使用收到填充因子的影響。



 

為了使得大家更加的清楚,我們還是繼續看例子。

下面,我們在表上面把索引重建,如下:

ALTER  INDEX PK_AgileSharp_FillFactorDemo  ON dbo.AgileSharp_FillFactorDemo REBUILD

SELECT  object_id, index_id, avg_page_space_used_in_percent
FROM sys.dm_db_index_physical_stats( DB_ID(), OBJECT_ID( ' dbo.AgileSharp_FillFactorDemo '), NULL, NULL, ' DETAILED ')
WHERE index_level  =  0

結果如下:


 

下面,為了證明上面的講述,我們再來看一個例子,
首先,我們還是來建立一個表,如下:

 

CREATE  TABLE dbo.AgileSharp_FillFactorConfirm
(
RowID  int  NOT  NULL
,Column1  varchar( 500)
);

ALTER  TABLE dbo.AgileSharp_FillFactorConfirm  ADD  CONSTRAINT
PK_AgileSharp_FillFactorConfirm  PRIMARY  KEY  CLUSTERED (RowID)  WITH( FILLFACTOR  =  50);

 

然后我們插入數據,我們此時插入的RowID都是偶數,如下:
declare  @ID  int
set  @ID = 0
while  @ID <= 2000
begin
set  @ID = @ID + 2;
Insert  into AgileSharp_FillFactorConfirm  values( @ID, ' AgileSharp Confirm FillFactor ')

end
數據就可能如下:
我們查看查看索引頁的使用情況和索引頁的個數,如下:
SELECT  object_id, index_id, avg_page_space_used_in_percent,page_count
FROM sys.dm_db_index_physical_stats( DB_ID(), OBJECT_ID( ' dbo.AgileSharp_FillFactorConfirm '), NULL, NULL, ' DETAILED ')
WHERE index_level  =  0
結果如下:
上述結果還是和我們之前講述的一樣:填充因子沒有起作用。

然后我們重建索引,如下:
ALTER  INDEX PK_AgileSharp_FillFactorConfirm  ON dbo.AgileSharp_FillFactorConfirm REBUILD
然后再次查看,結果如下:

此時,我們看到,頁的填充率大約是47%,我們可以試想:我們在表中插入奇數的RowID,此時頁面數應該是不變的,而且填充率會變為94%。如果結果真是這樣,那么就說明填充因子起作用了。
我們插入數據,如下:
declare  @ID  int
set  @ID = 1
while  @ID <= 2000
begin
set  @ID = @ID + 2;
Insert  into AgileSharp_FillFactorConfirm  values( @ID, ' AgileSharp Confirm FillFactor ')

end
然后,我們查看索引頁的情況,如下:
好,結果如我們所望,也就證明了上面我們的說法。
其實大家可以查看頁上面的詳細信息,我這里就不多說了。


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM