Microsoft SQL Server 2000 索引碎片整理最佳實踐

原文:Microsoft SQL Server 2000 Index Defragmentation Best Practices
來源:Microsoft TechNet
作者:Mike Ruthruff
時間:February 2003

Summary As Microsoft SQL Server 2000 maintains indexes to reflect updates to their underlying tables, these indexes can become fragmented. Depending on workload characteristics, this fragmentation can ......

 

--------------------------------------------------------------------------------


摘要 既然SQL Server 2000爲了反應數據的更新,需要維護表上的索引,因而這些索引會形成碎片。根據工作量的特徵,這些碎片會影響對應的工作性能。該白皮書提供能幫助你決定是否需要整理碎片以改善性能的信息。SQL Server 2000提供了一些命令來實現索引的碎片整理。這裏比較其中兩個命令:DBCC DBREINDEX 和 DBCC INDEXDEFRAG。

目錄

概述
瞭解碎片
整理碎片前需要考慮的因素
小規模環境 vs. 大規模環境
決定何時進行索引碎片整理
DBCC DBREINDEX vs. DBCC INDEXDEFRAG
結論
更多信息
附錄 A: 測試環境

 

 

概述

本白皮書提供在生產環境中,決定是否進行索引的碎片整理工作以改善工作性能的信息。另外,本文比較了Microsoft SQL Server 2000中用於索引碎片整理的兩個命令:DBCC DBREINDEX 和 DBCC INDEXDEFRAG。這個比較包括不同的數據庫和硬件環境的測試結果。關於測試環境,請見章節"小規模環境 vs. 大規模環境"和附錄A。

注意: 並不是在任何情況下,碎片整理都會改善性能。每個場景是不同的。也因爲如此,所以是否要進行碎片整理工作要根據分析結果而定。

白皮書敘述索引碎片整理的重要性以及常規處理流程。下面列舉本文的關鍵觀點:


在索引碎片整理前,請確保系統資源的一些問題,比如物理磁盤碎片,不合理的基礎結構等因素會給性能帶來負面影響。
DBCC SHOWCONTIG可以顯示索引碎片數量。當運行該命令時,要特別注意邏輯碎片(Logical Fragmentation)和頁密度(Page Density)兩個指標。
決定是否要碎片整理,考察工作類型很重要。不是所有情況下,都能從碎片整理中受益。對讀取比較多的工作類型來說,磁盤I/O是最重要的性能指標。測試顯示決策支持系統(DSS: Decision Support System)比很多在線事務處理系統(OLTP: Online Transaction Processing),從碎片整理中獲益更多。
碎片將影響磁盤性能和SQL Server預讀管理(read-ahead manager)的效果。Windows性能監視器有幾個關鍵指標可以用來支持這一觀點。
決定是否用 DBCC DBREINDEX 還是 DBCC INDEXDEFRAG 取決於你的需求以及硬件環境。
DBCC DBREINDEX會帶來更新統計(updating statistics)的副作用,而DBCC INDEXDEFRAG不會。可以通過在執行DBCC INDEXDEFRAG後執行UPDATE STATISTICS來增加其影響。

 

瞭解碎片

當索引所在頁面的基於主關鍵字的邏輯順序,和數據文件中的物理順序不匹配時,碎片就產生了。所有的葉級頁包含了指向前一個和後一個頁的指針。這樣就形成一個雙鏈表。理想情況下,數據文件中頁的物理順序會和邏輯順序匹配。整個磁盤的工作性能在物理順序匹配邏輯順序時將顯著提升。對某些特定的查詢而言,這將帶來極佳的性能。當物理排序和邏輯排序不匹配時,磁盤的工作性能會變得低效,這是因爲磁頭必須向前和向後移動來查找索引,而不是隻象某個單一方向來搜索。碎片會影響I/O性能,不過對於位於SQL Server數據緩衝內的數據頁而言,碎片並不會帶來任何影響。

當索引第一次創建時,沒有或者只有極少碎片。隨着時間推移,插入,更新和刪除數據,和這些數據相關的索引上的碎片就增加了。爲了整理碎片,SQL Server提供如下命令:


CREATE INDEX後的DROP INDEX命令
不帶DROP_EXISTING選項的CREATE INDEX命令
DBCC INDEXDEFRAG
DBCC DBREINDEX

本文用 DBCC INDEXDEFRAG 和 DBCC DBREINDEX 命令來進行測試。這些命令都可以在在線和離線場景下執行。DBCC DBREINDEX按照CREATE INDEX的方式創建索引;因此DBCC DBREINDEX的執行結果和用CREATE INDEX命令的結果很相似。上面所有這些命令的測試結果和功能描述會在本文後面提到。

 

整理碎片前需要考慮的因素

系統資源問題

在索引碎片整理之前,要確認系統任何性能問題和系統資源限制無關。關於這方面的詳細討論已經超出了本文的範圍,不過有些更常見的資源問題和I/O子系統性能,內存使用以及CPU使用率相關。關於分析這些類型資源問題的更深入討論,請見本文最後的“更多的信息”章節。

物理磁盤碎片

在某些系統上,磁盤碎片會帶來很糟的性能。要確定是否存在磁盤碎片,可以使用Microsoft Windows自帶的系統工具,或者第三方提供的工具來分析SQL Server所在的分區。對於常規的I/O子系統上的規模較小的數據庫,建議在運行索引碎片整理工具前,先進行磁盤碎片整理。而對於更智能的磁盤子系統上的規模較大的數據庫,例如SAN(存儲區域網絡 storage area networks)環境,磁盤碎片整理就不是必要的。

執行情況較差的查詢

當考察任何性能相關問題時,你必須能識別出那些查詢執行效率較差。這裏討論的一些信息在後面也會用到,這些信息用於決定那些索引碎片將被整理。

可以使用SQL Profiler(事件探查器)來識別執行效率差的查詢(關於這方面更多的信息,請參考SQL Server聯機幫助的"SQL Profiler"主題)。運行SQL Profiler會帶來開銷;不過,只監控下面介紹的一些事件可以收集到必要的信息,而且對性能的影響儘可能的小(一般來說,小於10%的CPU使用率,當然有根據情況有些差異)。

SQL Profiler提供了一個名叫SQLProfilerTSQL_Duration的跟蹤模板,可以捕獲相關的事件。可以很快捷地利用它來識別執行效率較差的查詢。也可以手工創建SQL Profiler跟蹤來捕獲下述事件:


TSQL: SQLBatchCompleted
Stored Procedures: RPC:Completed

運行SQL Profiler的時間長度要根據服務器工作量而定。爲了讓跟蹤更有效,需要選擇代表性的任務類型,至少應該選擇那些能顯示性能低下的工作類型。當跟蹤被捕獲後,檢場跟蹤日誌中持續時間那列數據。該列數據以毫秒爲單位,表示每個批處理或者查詢運行需要的時間。

標識出引起性能最差的查詢

這裏列舉能夠標識出造成最糟糕性能的查詢的一些建議:


按查詢持續時間對跟蹤進行分組。將注意力首先放在前10個最差的查詢上。
如果在應用中大量使用了存儲過程,考慮使用SQLProfilerSP_Counts模板來標識被調用最多的那些存儲過程。將注意力放在被調用最頻繁,同時也是引起較差性能的存儲過程。
將收集的數據放到SQL Server表中。這樣,就可以通過查詢表來對工作性能進行更爲詳細的分析(例如,平均運行時間,最大運行時間,等等)。

基礎結構

當找出運行時間最長,性能最差得查詢後,必須確保數據庫基礎架構對於那個查詢來說是最優的。例如確保存在適當的索引並且被那個查詢正確地使用了。可以使用查詢分析器來顯示和檢查查詢計劃,以發現在查詢任務中那些索引被用到了。當使用查詢分析器圖形化顯示查詢的執行計劃時,以前的數據會以警告的方式標識(例如表名會以紅色字體顯示)。在整理碎片之前要解決這些問題。

檢查查詢計劃時,要牢記以下建議:


找到執行計劃中開銷較大的步驟。這些步驟是查詢中最耗時的部分。解決這些步驟帶來的問題將會使性能大幅提高。
找出執行索引掃描的步驟。索引掃描是從碎片整理中獲利最大的部分。注意那些性能較差的查詢索引掃描中用到的索引,在碎片整理的時候可以集中在這些索引上進行。

利用SQL Profiler中捕獲的跟蹤信息,以及手工從查詢計劃中獲取的信息,就可以使用索引向導(Index Tuning Wizard)來分析工作量。利用索引想到生成的報表來決定是否要對基礎結構做改動。在碎片整理前做完這些改動。

 

小規模環境 vs. 大規模環境

這裏做的測試基於兩臺服務器,兩臺服務器之間的I/O子系統相差很大。一臺服務器代表小規模環境,而另一臺代表大規模環境。用來解釋測試結果,每臺環境的規格如下。

小規模環境

在小規模環境中,數據庫大小在10GB-20GB之間。數據分佈再兩個物理磁盤上,tempdb和數據庫日誌分別在兩個使用RAID 0的額外磁盤上。DSS數據庫包含兩個文件組,每個文件組內有一個文件。OLTP數據庫只包含一個文件組,文件組內有一個數據文件。

大規模環境

Micorosoft和Hitachi Data System系統配合,可以用Hitachi Freedom Storage Lightning 9900 Series Lightning 9960 system來構建SAN環境,用於存儲數據。用於測試的那個數據庫大小大約爲1TB。數據分散在64個物理磁盤上,使用RAID1+0結構。存儲數據的磁盤由8個LUNs(Logical Unit Numbers)連接,數據庫包含一個文件組,該文件組中包含8個數據文件。tempdb和數據庫日誌單獨放在一組磁盤上,與數據文件隔離開,48個磁盤用於存放tempdb,而日誌分佈在8個磁盤上。爲了快速備份和恢復有碎片的數據庫鏡像,在SAN中維護中有兩個Hitachi ShadowImage拷貝數據/日誌備份,Lightning 9960系統用於同步在線數據和ShadowImage備份數據。在該環境中,重複在三個碎片級別上運行兩次,因爲大容量的存儲需要維護每個級別(大約1.4TB)的備份。

索引碎片整理對性能的影響

測試結果在後面會詳細討論。但是,雖然碎片整理對兩個環境(小規模和大規模)環境都帶來負面影響,但是無疑對大規模環境的影響要小得多。因爲大規模環境從SAN中獲取了極高的I/O性能,因此這個結論應該是對的:數據不光分散在多個磁盤上,而且SAN還提供16GB的數據緩衝區。I/O benchmark測試顯示創建1TB數據量,最大的讀取速度爲354 MB/sec, 而小規模環境下只有71 MB/sec。

注意: 這些數值會根據各人的實現步驟和存儲配置而變。

顯然,高性能的I/O子系統對SQL Server性能十分有利,不過,索引碎片整理的確會對所有系統帶來性能的提升。當創建數據庫時,要謹慎考慮I/O子系統,並確保儘可能將日誌文件和數據庫數據文件隔離開。

 

決定何時進行索引碎片整理

決定何時進行索引碎片整理時,請考慮以下重要的建議:


標識有碎片的索引。
瞭解何種任務會從碎片整理中獲利。
確定查詢的I/O性能。
理解碎片整理帶來的影響和SQL Server預讀管理器。

下一節中,測試的結果可以用來幫助理解這些建議。

使用 DBCC SHOWCONTIG 來標識有碎片的索引

在決定何時進行碎片整理前,必須先確定那些索引有碎片。DBCC SHOWCONTIG可以用於衡量索引上的碎片程度和頁密度級別(Page Density level)。

下面是運行 DBCC SHOWCONTIG 後的得到的示例信息:

DBCC SHOWCONTIG scanning 'table_1' table...
Table: 'table_1' (453576654); index ID: 1, database ID: 8
TABLE level scan performed.
- Pages Scanned................................: 48584
- Extents Scanned..............................: 6090
- Extent Switches..............................: 12325
- Avg. Pages per Extent........................: 8.0
- Scan Density [Best Count:Actual Count].......: 49.27% [6073:12326]
- Logical Scan Fragmentation ..................: 10.14%
- Extent Scan Fragmentation ...................: 32.74%
- Avg. Bytes Free per Page.....................: 1125.2
- Avg. Page Density (full).....................: 86.10%
DBCC SHOWCONTIG scanning 'table_1' table...
Table: 'table_1' (453576654); index ID: 2, database ID: 8
LEAF level scan performed.
- Pages Scanned................................: 41705
- Extents Scanned..............................: 5221
- Extent Switches..............................: 6094
- Avg. Pages per Extent........................: 8.0
- Scan Density [Best Count:Actual Count].......: 85.55% [5214:6095]
- Logical Scan Fragmentation ..................: 7.80%
- Extent Scan Fragmentation ...................: 6.63%
- Avg. Bytes Free per Page.....................: 877.7
- Avg. Page Density (full).....................: 83.20%

 


檢查DBCC SHOWCONTIG運行後的結果時,需要特別留意Logical Scan Fragmentation和Average Page Density。Logic scan fragmentattion表示索引上亂序的百分比(注意: 該數值和堆和文本索引不相關。所謂堆表示一個沒有聚集索引的表。)。Page density是索引葉級頁填充程度的度量。請查找SQL Server聯機幫助的“DBCC SHOWCONTIG”主題以獲取更多信息。

分析DBCC SHOWCONTIG的輸出結果

在分析DBCC SHOWCONTIG的輸出結果時,請考慮下面問題:


碎片會影響I/O。因此,要集中關注較大的索引,因爲這些索引被SQL Server放入緩存的可能性比較小。通過DBCC SHOWCONTIG得到的頁數,可以估算出索引的大小(每頁大小爲8KB)。一般來說,沒有必要關注那些碎片級別小於1,000頁的索引。在測試中,包含超過10,000頁的索引纔會影響性能,特別是包含更多的頁(超過50,000頁)的索引,會引起最大的性能提升。
邏輯掃描碎片(logical scan fragmentation)值太高,會大大降低索引掃描的性能。在測試中,那些邏輯碎片大於10%的聚集索引,在碎片整理後性能得到了提升;對那些大於20%的聚集索引,性能提升尤其明顯。因此關注那些邏輯碎片大於等於20%的索引。注意,對於堆(Index ID=0)來說,該標準是無意義的。
平均頁密度(average page density)太低,將導致查詢中需要讀取更多的頁。重新組織這些頁,可以提高平均頁密度,從而完成相同的查詢只要讀取較少的頁。一般來說,在第一次載入數據後,表擁有較高的頁密度。隨着數據的插入,頁密度會降低,從而帶來葉級頁拆分。檢查平均頁密度時,記住該值依賴於創建表時設置的填充因子取值。
雖然掃描密度(scan density)可以作爲碎片級別的參考,不過當索引跨越多個文件時,該參考無效。因此,當檢查跨越多個文件的索引時,掃描密度不應該被考慮。

監視碎片級別

有規律地監控索引的碎片級別是良好的實踐習慣。SQL Server聯機幫助的"DBCC SHOWCONTIG"主題中,有一個示例腳本,用於自動捕獲和重建碎片程度較大的索引。建議每隔一段固定時間就使用帶TABLERESULTS選項的DBCC SHOWCONTIG命令,將得到的結果保存在表內。這樣做可以使你不受時間限制地監控碎片級別。另外,還建議在繁忙的服務器上使用帶有WITH FAST選項的DBCC SHOWCONTIG命令。帶有WITH FAST選項的DBCC SHOWCONTIG命令可以避免掃描索引的葉級頁,從而是的執行比較快。不過,因爲它不掃描葉級頁,所以就無法報告頁密度指標。

表1 顯示在小規模和大規模DSS環境下,運行DBCC SHOWCONTIG命令所需的時間。每次測試中,都帶 ALL_INDEXES 和 TABLERESULTS 選項。 表1 DBCC SHOWCONTIG 執行結果 DBCC SHOWCONTIG options Total number of index pages (all indexes) Run time (minutes)
Small-Scale Environment   
Not using the WITH FAST option 1,702,889 5.02
Using the WITH FAST option 1,702,889 0.90
Large-Scale Environment   
Not using the WITH FAST option 111,626,354 382.35
Using the WITH FAST option 111,626,354 48.73


理解哪些工作類型從索引的碎片整理中獲益最多

當你決定進行索引的碎片整理時,理解有些工作類型將比另一些工作類型從碎片整理中獲益更多這個結論,是十分重要的。碎片會對I/O帶來負面影響。在大範圍內用到索引頁的查詢受碎片的影響最大,從而也最能從碎片整理中獲益。

測試利用兩種數據庫工作類型,比較了碎片整理前和整理後的性能。測試對象包括了具有代表性的OLTP和DSS數據庫。OLTP數據庫上的工作主要集中在特定範圍的數據的更新(insert,update和delete)和有選擇性的讀取。而對於DSS系統,由於主要是讀取工作類型,因此測試集中在多表聯接的查詢任務。特別是這些查詢必須需要掃描到一個或更多的索引。測試結果表明碎片對OLTP工作影響極小,而對DSS系統則從碎片整理獲益多多。

DBCC INDEXDEFRAG 和 DBCC DBREINDEX 命令常用來整理索引碎片。對這兩個命令特定功能的更詳細討論後面會涉及到。

OLTP型工作量

測試中,OLTP數據庫模擬數據倉庫環境下的訂單處理流程。工作量包括5個存儲過程,涉及流程包括新建訂單,訂單狀態查詢,分發,庫存狀態,以及交付流程。存儲過程中用到了插入,更新和刪除語句以及有目的選擇的SELECT查詢。

圖1 顯示了使用DBCC INDEXDEFRAG 和 DBCC DBREINDEX 進行索引碎片整理前後,每個存儲過程完成查詢時性能的差異。

圖1: 碎片整理前後,OLTP型工作環境下,每個存儲過程的平均執行時間。值越小表示性能越好。點擊看原圖
--------------------------------------------------------------------------------

如圖1所示,碎片整理前後,存儲過程性能差別不是很大。因爲存儲過程中的基礎查詢有選擇性地選取部分數據,因此索引碎片給性能帶來的影響不大。圖1還顯示運行碎片整理工具的確降低存儲過程的性能;不過在存儲過程運行期間本身就會給性能帶來10%-20%之間的波動。圖1顯示的差異也在這個範圍之內。更重要的是,結果顯示當碎片級別上升時,並未帶來存儲過程性能的下降。

DSS型工作量

測試中,DSS工作量包含22個由複雜SELECT語句構成的報表類型的查詢。這些查詢嚴格地以批處理方式在服務器端運行。所有查詢包含一個或多個多表聯接,大多數查詢需要掃描很大範圍的索引。

表2 記錄測試中用到的索引的平均碎片和頁密度級別。碎片級別通過下屬行爲組合得到:


以Bulk INSERT方式插入新數據到數據庫,並模擬週期性地刷新數據。
刪除某個範圍內的數據。
按關鍵值執行一些更新操作,雖然這至少會影響碎片級別,不過和插入和刪除操作相比,更新涉及到的記錄相對還是比較少。
表2 小規模和大規模環境中平均邏輯碎片和頁密度測試 Fragmentation level Average logical fragmentation (%) Average page density (%)
Small-Scale Environment   
Low (1) 7.8 80.1
Medium (2) 16.6 68.1
High (3) 29.5 69.2
Large-Scale Environment   
Low (1) 5.9 84.4
Medium (2) 13.8 70.3


DSS工作類型的測試結果和OLTP工作類型相差很大。在整理索引碎片後,性能提高很明顯。因爲此時工作量的性能強烈依賴於磁盤吞吐量(大多數查詢會包含索引掃描),因此該結果是可以預料到的。下面的圖2和圖3顯示DSS型工作量在整理索引碎片前後的性能收益情況。如圖中所示,性能從碎片整理中顯著提升。

在小規模環境中,在碎片較低級別,性能提升了60%,而在碎片較高級別提升了460%。在大規模環境中,在碎片較低級別性能提升13%,在中等級別提升了40%。結果顯示大規模環境中,碎片對性能影響影響相對較小,這是因爲該環境從磁盤子系統的表現獲益更多一些。更詳細的討論見本文後面的“碎片對磁盤吞吐量的影響和SQL Server預讀管理器”章節。

圖2: 小規模環境下,整個DSS型工作量在不同碎片級別下的運行時間。取值越低表示性能越好。 點擊看原圖
--------------------------------------------------------------------------------
圖3: 大規模環境下,整個DSS型工作量在不同碎片級別下的運行時間。取值越低表示性能越好。點擊看原圖
--------------------------------------------------------------------------------

圖2從數值上顯示,在小規模環境下,DBCC INDEXDEFRAG的結果比DBCC DBREINDEX要好一些。不過,在大多數情況下,完全重建索引應該具有更好的性能。

在解釋這些測試結果時,需要牢記以下幾點:


圖2和圖3顯示的結果意味着這是應用DBCC INDEXDEFRAG的“最佳”場合。測試中,DBCC INDEXDEFRAG運行在一個禁止的系統上;因此DBCC INDEXDEFRAG可以完全消除碎片。當DBCC INDEXDEFRAG運行在一個動態的系統上,即數據保持在線更新,DBCC INDEXDEFRAG會跳過那些被鎖住的頁。因此DBCC INDEXDEFRAG也許就無法完全消除碎片。要衡量DBCC INDEXDEFRAG發揮了多大作用,可以在DBCC INDEXDEFRAG後立刻運行DBCC SHOWCONTIG。
數據的分佈情況會影響磁盤性能。小規模環境中,數據只分布在兩個物理磁盤(磁盤容量加起來一共33.5GB)上,在數據庫創建前,這兩個磁盤是空的。數據庫創建後,數據文件大小在22GB到30GB之間。當數據庫創建時,數據分佈在磁盤外圍部分。DBCC INDEXDEFRAG整理碎片也是從最鄰近原始數據的位置開始。因爲DBCC DBREINDEX完全重建索引,在釋放舊的索引頁前,它必須首先給新索引頁分配空間。分配新空間使得數據離原始數據位置較遠,並且分佈在磁盤內側,因此造成I/O吞吐量有輕微的下降。在小規模環境下的benchmark測試中,這種下降表現爲讀取數據吞吐量下降15%。
剩餘空間容量同樣會影響DBCC DBREINDEX。如果沒有大量連續的空閒空間,DBREINDEX會強迫使用數據文件中的空閒空間,從而導致索引重建時帶有一小部分數量的邏輯碎片。關於DBCC DBREINDEX對剩餘空間的需求的信息,見本文後面的"DBCC DBREINDEX"章節。

確定查詢的I/O流量

因爲具有大量I/O讀寫的查詢從碎片整理中獲益最多,所以討論如何確定某個特定查詢的I/O流量是必要的。SET STATISTICS IO命令可以報告完成一個特定查詢時,服務器實例上的讀取量和讀取類型。可以在查詢管理器中選擇該命令開關爲ON和OFF,使用方法如下:

SET STATISTIC IO ON
GO
SELECT * FROM table_1
GO
SET STATISTIC IO OFF
GO

 

 

輸出示例
Table 'table_1'.
Scan count 1,
logical reads 12025,
physical reads 0,
read-ahead reads 11421.

 


表3 關於SET STATISTIC IO 輸出結果的描述 Value Description
Scan count Number of scans performed
logical reads Number of pages read from the data cache
physical reads Number of pages read from disk
read-ahead reads Number of pages placed into the cache for the query


通過physical reads和read-ahead reads值,可以對某個特定查詢涉及的I/O量有一個估計。physical reads和read-ahead reads都表示從磁盤讀取的頁數。多數情況下,read-ahead reads比physical reads數值要大。

注意 在通過SQL Profiler 獲取信息時,reads列表示的是邏輯讀取量(logical reads),而不是物理讀取量(physical reads)。

除了重新對頁進行排序,通過增加索引葉級頁的頁密度,索引的碎片整理還降低執行某個查詢的I/O數量。頁密度的提高導致完成相同的查詢需要讀取更少的頁,從而提高性能。

理解碎片整理帶來的影響和SQL Server預讀管理器

碎片對大量讀取磁盤邊緣的操作帶來負面影響。可以使用Windows性能監視器來獲取這種影響的衡量。通過性能監視器,可以觀測磁盤活動情況,並且有助於決定何時進行碎片整理。

爲了理解爲什麼碎片對DSS型工作具有如此的影響,首先很重要的是要理解碎片是如何影響SQL Server預讀管理器的。爲了完成需要掃描一個或多個索引的查詢,SQL Server預讀管理器負責提前對索引頁進行掃描,並且將額外的數據頁放到SQL Server數據緩存中。根據基礎頁的物理順序,預讀管理器動態地調整讀取量。當碎片較少時,預讀管理器即時可以讀取較大的數據塊,更高效地利用I/O子系統。當數據產生碎片時,預讀管理器只能讀取較小的數據塊。預讀的數量雖然和數據的物理順序無關,不過,因爲較小的讀取請求消耗更多的CPU/時鐘,所以最終就會降低整個磁盤的吞吐量。

在所有情況下,預讀管理器能提高性能;但是,當存在碎片,且預讀管理器無法讀取較大的數據塊,整個磁盤的吞吐量就下降。通過檢查性能監視器中的Physical Disk相關的計數器可以發現該現象。下表列舉並描述了這些計數器。 表4 性能監視器中物理磁盤計數器 Physical Disk counter Description
Avg Disk sec/ Read 該計數器用於衡量磁盤延遲。測試顯示當碎片出於很高水平(大於等於30%)時,會增加磁盤延遲。
Disk Read Bytes/ sec 該計數器能很好地衡量全面的磁盤吞吐量。一段時間內工作量的下降趨勢可以用來表示碎片正在影響性能。
Avg Disk Bytes/ Read 該計數器用於衡量每個讀取請求帶來的數據讀取量。當索引頁連續,SQL Server預讀管理器可以一次讀取較大的數據塊,對I/O子系統的利用效率較高。測試顯示該計數器值和碎片數量間有着直接聯繫。當碎片級別上升,該值就下降,從而影響全面的磁盤吞吐量。
Avg Disk Read Queue Length 一般而言,該計數器爲每兩個物理磁盤上持續的平均數值。測試中,很可能由於較高的延遲和較低的全面磁盤吞吐量,使得該計數器隨着碎片的增加而增加。


圖4到圖7顯示在DSS型工作中,性能監視器報告的磁盤吞吐量和平均讀取大小。

圖4: 小規模環境下,DSS工作流的磁盤吞吐量。數值越高表示磁盤吞吐能力越好。點擊看原圖
--------------------------------------------------------------------------------
圖5: 小規模環境下,DSS工作流的磁盤吞吐量。數值越高表示磁盤吞吐能力越好。點擊看原圖
--------------------------------------------------------------------------------
圖6: 小規模環境下,DSS工作中每次磁盤讀取的平均大小。數值越高表示每次讀取字節數越多。點擊看原圖
--------------------------------------------------------------------------------
圖7: 小規模環境下,DSS工作中每次磁盤讀取的平均大小。數值越高表示每次讀取字節數越多。點擊看原圖
--------------------------------------------------------------------------------

上面的圖顯示碎片對磁盤性能的影響趨勢。雖然使用DBCC DBREINDEX和DBCC INDEXDEFRAG得到的結果不同,但是注意在所有系統上,都得到了一致的結果,即每次讀取的平均大小和整體磁盤吞吐量隨着碎片的增加而降低。正如你所見的,整理所有碎片對磁盤吞吐量提高極大。

每次讀取的平均大小還可以用來展示,碎片是如何影響預讀管理器讀取較大數據塊的能力的。這點需牢記在心,不過,平均讀取數量較大並不總是意味着整體吞吐量較高。平均讀取量大表示數據傳輸中,CPU負荷較小。當索引沒有碎片時,讀取64KB大小數據的速度和讀取256KB大小數據的速度幾乎一樣。這個結論在那些數據分佈在多個磁盤上的大型系統而言,尤其如此。這些普遍和特殊的結論,會根據不同的系統,因爲各種各樣的原因(例如,不同的I/O子系統,工作類型差異,數據在磁盤的分佈特徵等等)而不同。當監視系統時,尋找那些持續時間較長的磁盤吞吐量和讀取數量的下降階段。這些階段以及DBCC SHOWCONTIG命令提供的信息,可以用於幫助來確定什麼時候該進行索引的碎片整理了。

測試結果顯示碎片也會帶來磁盤延遲,不過,至於那些最高級別的碎片纔會對磁盤延遲帶來巨大的負面影響,並且也只在小規模環境下才有此現象。在大規模環境下,由於SAN提供了很高的I/O性能,因此磁盤延遲值十分小而從來不會帶來問題。

 

DBCC DBREINDEX vs. DBCC INDEXDEFRAG

除了使用CREATE INDEX命令來刪除或者重新創建索引,還可以使用DBCC DBREINDEX和DBCC INDEXDEFRAG命令來幫助維護索引。

DBCC DBREINDEX

DBCC DBREINDEX用於在指定的表上重建一個或多個索引。DBCC DBREINDEX是離線操作方式。當該操作運行時,涉及到的表就無法被用戶訪問。DBCC DBREINDEX動態地重建索引。沒有必要知道參與重建的表結構到底如何,是否用主鍵或者唯一性約束等信息;重建的時候會自動管理的。DBCC DBREINDEX完全重建索引,也就是說,將頁密度級別恢復到最初(默認)的填充因子水平;當然你也可以選擇頁密度的新值。從內部運行看,DBCC DBREINDEX和手工用T-SQL語句來運行刪除然後重新創建索引十分相似。

下面兩點是DBCC DBREINDEX比DBCC INDEXDEFRAG優越的地方:


DBCC DBREINDEX在重建索引過程中,自動重建統計;這將顯著提高工作性能。
DBCC DBREINDEX可以運行在多處理器環境下,利用多處理器的優勢,當重建較大和碎片厲害的索引時,速度可以十分快。

DBCC DBREINDEX的所有工作是一個單一的,原子事務。必須完成創建新的索引並替換舊索引,然後舊索引頁被釋放。完成重建需要數據文件中有足夠的空餘空間。如果空餘空間不夠,DBCC DBREINDEX要麼無法重建索引,要麼會產生大於0的邏輯碎片。所需空餘空間視情況而定,取決於事務中要創建的索引數目。對於聚集索引而言,一個不錯的指導公式爲:所需空餘空間 = 1.2 * (平均行大小) * (行數量)。

對於非聚集索引,可以通過計算非聚集索引包含的每行平均大小(非聚集索引包含關鍵字長度 + 聚集中的索引關鍵字或者row ID長度)乘以行數量得到所需空間。如果對整個表進行索引重建,需要爲聚集索引和非聚集索引留出足夠的空間。同樣,如果重建不唯一非聚集索引,也需要爲聚集和非聚集索引留出空餘空間。因爲SQL Server必須爲每行創建唯一標識,因此非聚集索引是隱式重建的。使用DBCC DBREINDEX時,較佳的做法是指定那些索引需要整理。這樣做可以使得對操作有更多的控制力,以及避免不必要的麻煩。

DBCC INDEXDEFRAG

DBCC INDEXDEFRAG用於對指定的索引進行重建。和DBCC DBREINDEX類似,也不需顧及表的基礎結構;不過,DBCC INDEXDEFRAG無法用一個語句對所有的索引進行重建。對於每個希望進行碎片整理的索引,都必須運行一次DBCC INDEXDEFRAG。

和DBCC DEREINDEX不同的是,DBCC INDEXDEFRAG是在線操作的;因此在整理索引碎片時,仍然可以訪問被整理到的表和索引。另外一個和DBCC INDEXDEFRAG很不同的地方是,DBCC INDEXDEFRAG可以中止和重新開始而不丟失任何工作信息。整個DBCC DBREINDEX操作作爲一個原子事務運行。這意味着如果中止DBCC DBREINDEX操作,整個操作會回滾,繼續的話必須重新開始。但是,如果中止DBCC INDEXDEFRAG,任務會立刻中止並不會丟失已經完成的任務,因爲DBCC INDEXDEFRAG每個工作單位是獨立的事務。

DBCC INDEXDEFRAG包括兩個階段:


壓縮頁並試圖根據索引創建時指定的填充因子來調整頁密度。DBCC INDEXDEFRAG會根據最初的填充因子,儘可能提高頁密度級別。而DBCC INDEXDEFRAG不會,但是它會將那些高於最初填充因子的頁密度降低。
通過移動頁來使得物理順序和索引葉級頁的邏輯順序一致,從而整理索引碎片。這個工作由一系列獨立的很小的事務來完成;因此DBCC INDEXDEFRAG對整體系統性能,影響很小。圖8顯示DBCC INDEXDEFRAG的碎片整理階段中頁移動情況。

圖8: DBCC INDEXDEFRAG的數據文件頁移動情況
--------------------------------------------------------------------------------

DBCC INDEXDEFRAG並不會幫助整理分散插入到數據文件中的索引,這種分散插入稱爲Interleave。同樣,DBCC INDEXDEFRAG也不對擴展頁碎片進行整理。當索引擴展頁(擴展頁=8頁)中的數據並不連續的時候,出現Interleave,此時多個擴展頁的數據在文件中是交叉狀態。因爲即使邏輯順序和物理順序一致情況下,所有的索引頁也不見得一定是連續的,因此即使沒有邏輯碎片情況下,Interleave也會存在。

雖然上面提到了DBCC INDEXDEFRAG的限制,但是測試顯示,DBCC INDEXDEFRAG對性能的改善和DBCC DBREINDEX一樣有用。實際上,從測試結果可以看出,即使重建了索引,使得Interleave最小,這部分優化並不會對性能帶來顯著提升。減少邏輯碎片級別這部分優化纔對性能提升最多。這就是爲什麼檢查索引碎片時,建議將重點放在邏輯碎片整理和頁密度碎片上的原因。表5總結了DBCC DBREINDEX和DBCC INDEXDEFRAG之間的差別。 表5 DBCC DBREINDEX 和 DBCC INDEXDEFRAG的比較 Functionality DBCC DBREINDEX DBCC INDEXDEFRAG
Online/Offline Offline Online
Faster when logical fragmentation is: High Low
Parallel processing Yes No
Compacts pages Yes Yes
Can be stopped and restarted without losing work completed to that point No Yes
Able to untangle interleaved indexes May reduce interleaving No
Additional free space is required in the data file for defragmenting Yes No
Faster on larger indexes Yes No
Rebuilds statistics Yes No
Log space usage High in full recovery mode (logs entire contents of the index), low in bulk logged or simple recovery mode (only logs allocation of space) Varies based on the amount of work performed
May skip pages on busy systems No Yes


性能: DBCC DBREINDEX vs. DBCC INDEXDEFRAG

測試顯示,無論是DBCC DBREINDEX還是DBCC INDEXDEFRAG,都可以有效地整理索引碎片,並將頁密度恢復到初始填充因子規定的頁密度附近。基於這些結果,下面需要決定什麼時候應用哪種整理方式。

如果允許有一段時間進行離線索引重建,DBCC DBREINDEX一般來說比DBCC INDEXDEFRAG要快。DBCC DBREINDEX可以充分利用多處理器系統的平行性能。DBCC INDEXDEFRAG用於對生產環境干擾不大,對工作性能影響不大的場合。測試顯示,即使同時幾個DBCC INDEXDEFRAG並行工作,對性能下降的影響也從來不會超出10%。但是,這也同樣使得DBCC INDEXDEFRAG針對較大的索引整理時,需要很長的時間才能完成。而且,工作時間的長短還依賴於當時在服務器上運行的訪問工作。

圖9爲DBCC INDEXDEFRAG和DBCC DBREINDEX的性能比較。圖中的數據爲小規模環境下,對所有索引進行整理的時間(大規模環境下結果類似,DBCC INDEXDEFRAGY運行時間爲DBCC INDEXREINDEX的8倍)。當碎片級別增加,索引大小增加時,DBCC DBREINDEX可以比DBCC INDEXDEFRAG執行得更快。

圖9: 小規模環境下,整理所有索引碎片所需時間點擊看原圖
--------------------------------------------------------------------------------

日誌考慮: DBCC DBREINDEX vs. DBCC INDEXDEFRAG

最後要考察的問題是使用DBCC INDEXDEFRAG和DBCC DBREINDEX時,寫入事務日誌的數據量差別。DBCC INDEXDEFRAG中寫入事務日誌的數據量依賴於碎片的級別和完成的工作量。測試顯示,當數據庫完全恢復模式下,DBCC INDEXDEFRAG寫入事務日誌的數據量遠遠小於DBCC DBREINDEX。DBCC INDEXDEFRAG的日誌數據量,可以變化很大。這是因爲DBCC INDEXDEFRAG完成的碎片整理工作量由頁移動數量和必要的頁壓縮數量決定。因爲DBCC INDEXDEFRAG工作由一系列小事務組成,因此可以通過備份來回收DBCC INDEXDEFRAG使用的那部分日誌空間。

從日誌使用的角度看,DBCC DBREINDEX和DBCC INDEXDEFRAG稍有不同;在大批量(bulk)日誌恢復模式下,日誌量具有最大的差異。在完全恢復模式下,DBCC DBREINDEX對每個索引頁有日誌鏡像,在日誌恢復模式下,就沒有。因此,在完全恢復模式下,DBCC DBREINDEX所需的日誌空間大約等於索引頁數量乘以8KB。可以通過DBCC SHOWCONTIG來確定給定索引的頁數量。在大規模環境下,運行DBCC DBREINDEX時,建議將恢復模式改爲日誌恢復模式。而在運行結束後,再改爲完全恢復模式。

注意:由於大規模環境下,回滾事務需要付出巨大的時間代價,因此理解日誌的需求很重要。

圖10 顯示在小規模和中度碎片級別環境下,DBCC INDEXDEFRAG和DBCC DBREINDEX日誌空間使用的差別。雖然DBCC INDEXDEFRAG日誌空間波動很大,不過測試結果可以體現DBCC DBREINDEX和DBCC INDEXDEFRAG的一般性差別。

圖10: 對DSS型數據庫所有索引碎片整理時,DBCC INDEXDEFRAG和DBCC DBREINDEX所用的整個日誌空間點擊看原圖
--------------------------------------------------------------------------------

 

結論

對於不同的工作類型,索引碎片整理具有十分不同的影響。某些應用可以從碎片整理中獲取很大的性能提升。理解應用特徵,系統性能和SQL Server提供的碎片統計信息,是正確決定何時進行碎片整理的關鍵。SQL Server提供一些命令來完成索引碎片整理。本文可以幫助我們來決定何時以及如何整理索引碎片,從而使性能得到最大的改善。

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