SQL Server 查詢優化(4)_索引的碎片與管理

一、索引碎片

無論是索引組織表(IOT)還是堆表(HEAP),隨着數據的增刪改,都會或多或多的產生碎片。碎片的存在,主要對於數據掃描效率有着較大的影響,對於數據查找效率幾乎沒有影響或者說影響很小,如果想要改善數據查找的效率,進行索引碎片整理並沒有什麼效果。以下的碎片分類也主要是從數據掃描着眼。

1、內部碎片

內部指的是頁內,即頁面的空閒空間。其實填充因子就是一種碎片,爲了減少頁拆分,寧願適當地去製造這種碎片。但在大量內部碎片一直處於無法被數據填充的情況下,是沒有益處的,它會導致掃描過程中讀取額外的頁面。

對於LOBROW_OVERFLOW_DATA頁面,這是唯一的碎片形式,因爲在這兩種列上無法建立B樹索引。

 

2、外部碎片

1)邏輯碎片

索引葉子節點頁的邏輯順序與物理順序不一致,比如:有頁號12的兩個頁面,此時1頁面發生頁拆分,這時新申請的頁面頁號爲3,此時邏輯順序爲1-3-2,但物理順序是1-2-31頁面沒有直接指向磁盤的下一個物理頁,這就造成了不一致,即邏輯碎片;

 

2)擴展碎片

SQL SERVER通常給表或索引分配新的空間是以EXTENT(區或擴展)的形式,一個區是8個頁面,所以區的第一個頁號應該是8的倍數,比如:一個包含有序區的表,第一個頁面的頁號應該是8-16-24,這樣下去,如果是8-24,那麼說明第一個頁面頁號爲16的區被分配給了另一個表,那麼8-24的表在物理上就存在一個間隙,即擴展碎片;

 

外部碎片是對數據連續性的度量,擴展碎片是堆表數據連續性的度量,數據的連續性越差,掃描的成本也會越大。

 

二、查看與管理

對於索引樹的管理主要考慮兩方面:一是B樹的平衡性,這一點數據庫系統會自動維護;二是索引碎片,這需要手動去維護。

1、碎片的查看

SQL SERVER支持兩種碎片查看方式,至於這兩種碎片查看方式的使用方法,幫助文檔裏有很詳細的說明。

1dbcc showcontigSQL SERVER 2000中的唯一碎片查看方式,在SQL SERVER 2005中無法支持LOB類型、ROW_OVERFLOW_DATA及整個分區表的碎片查看;

 

2sys.dm_db_index_physical_statsSQL SERVER 2005新的碎片查看方式;

 

對於碎片的檢測以及是否需要進行碎片處理,主要從以下幾個參數來看:

1)內部碎片檢測

avg_page_space_used_in_percent:頁面空間平均使用比例;

對於數據掃描而言,該參數越大越好,這意味着讀取較少的頁面即可返回想要的數據。

 

fragment_countIN_ROW_DATA碎片的數量;

avg_fragment_size_in_pagesIN_ROW_DATA碎片的平均頁大小;

以上參數反應了行內數據頁碎片的數量及碎片的大小,即便碎片數量很多,但如果碎片很大即很整塊的話,通常要大於64KB即一個EXTENT,對於數據掃描而言,效率也是很高的,因爲SQL SERVER會跳過這些整塊的碎片。

 

ghost_record_countversion_ghost_record_count:虛影紀錄數;

對於數據掃描而言,該參數越小越好。

 

forwarded_record_count:前轉紀錄數;

前轉紀錄只會在堆中存在,對於數據掃描而言,是非常有幫助的。

 

2)外部碎片檢測

avg_fragmentation_in_percent:頁面平均外部碎片的比例;

對於數據掃描而言,該參數越小越好。

 

2、碎片的整理

1)、索引重建

顧名思義,重新建立索引,對索引的數據進行重新排列。在SQL SERVER 2000中這是一個脫機操作,即索引重建完成前,索引無法訪問或使用,在SQL SERVER 2005/2008中支持聯機操作。

 

聯機過程的實現,就是先維護另一份新索引,然後同步舊索引中變化的部分,同步完成後使用架構鎖鎖定舊索引,切換表到新的索引上,再釋放架構鎖,切換的過程是數據庫系統目錄的維護過程,速度很快,所以可以理解爲是聯機操作。

 

索引重建的方式有四種:

Adrop indexcreate index

這種方法是最差的,它會導致表上非聚集索引的兩次重建,一次在DROP時指向ROWID,一次在CREATE時重新指向聚集鍵。以下三種方法只需重新非聚集索引一次。

而且對於主鍵約束或唯一鍵約束產生的索引無法直接刪除,必須要先刪除約束,纔可以刪除索引;

 

Bcreate indexdrop_existing選項

這種方法完全重建索引,並可以重新指定索引參數;

 

Calter indexrebuild選項

這是SQL SERVER 2005/2008新的重建索引的方式,它不會重建非聚集索引,除非指定ALL關鍵字,同時它也更靈活,可以針對表上某個分區重建索引;

 

Ddbcc dbreindex

這是SQL SERVER 2000時重建索引的方法,它默認使用表上原來create index的參數重建索引。填充因子可重新指定。

 

2)、索引重組

將索引樹的葉節點頁重新排序,以消除外部碎片。這是一個聯機操作。但不同於索引重建的是,索引重組後統計信息不會得到更新,而且索引重組使用的是冒泡排序法,效率比較低。同時,索引重組只能在單個文件內進行,無法跨文件重組索引。

 

索引重組的方式有兩種:

Aalter indexreorgnize選項

這是SQL SERVER 2005/2008新的重組索引的方式,和dbcc indexdefrag一樣,它默認對錶上所有分區進行索引重組,不可以重新指定填充因子,因爲只是索引葉子節點的重新排序。但它比dbcc indexdefrag的選項更豐富些;

 

Bdbcc indexdefrag

這是SQL SERVER 2000時重組索引的方法。

 

注意:

1)碎片是不可避免,但並不是說一旦檢測到碎片就進行碎片整理,有時少量碎片的整理工作反而會帶來更大的成本消耗,所以在不能確定索引整理能否帶來良好性能時,不要輕易進行索引整理。

2)不管是內部碎片還是外部碎片,即便進行了碎片整理,也並不一定能夠完全消除,對於外部碎片,可以將表獨立存放在一個文件組上,並在文件初始化時分配足夠的磁盤空間,這樣的表經過碎片整理後外部碎片可以消除,但太過浪費磁盤空間;

3)無論是索引重建、索引重組都會對數據頁進行壓縮,頁面的填充程度由填充因子決定。它們都是事務操作,會產生日誌,爲了減少事務日誌的大小,可在索引整理後進行日誌截斷或日誌備份。

4)如有必要,對於DML非常頻繁的表,爲了保證數據掃描的效率,可以考慮利用作業來在系統相對空閒的時候定期進行索引整理。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章