一、必要性:
大多數SQL Server表需要索引來提高數據的訪問速度,如果沒有索引,SQL Server要進行表格掃描讀取表中的每一個記錄才能找到索要的數據。索引可以分爲簇索引和非簇索引,簇索引通過重排表中的數據來提高數據的訪問速度,而非簇索引則通過維護表中的數據指針來提高數據的索引。
在數據庫中創建索引時,查詢所使用的索引信息存儲在索引頁中。連續索引頁由從一個頁到下一個頁的指針鏈接在一起。當對數據的更改影響到索引時,索引中的信息可能會在數據庫中分散開來。重建索引可以重新組織索引數據(對於聚集索引還包括表數據)的存儲,清除碎片。這可通過減少獲得請求數據所需的頁讀取數來提高磁盤性能。
二、 何時需要重構索引,如何檢測?
爲了克服數據分塊帶來的負面影響,需要重構表的索引,這是非常費時的,因此只能在需要時進行。可以通過DBCC SHOWCONTIG來確定是否需要重構表的索引。
dbcc showcontig(’表名’);
以一個測試表爲例,輸出結果;
- Pages Scanned....................................: 197214 - Extents Scanned...............................: 24659 - Extent Switches DBCC...............................: 24658 - Avg. Pages per Exten.....................: 8.0 - Scan DensityBest Coun....................: 99.97%[24652:24659] - Extent Scan Fragmentation.............................: 15.46% - Avg. Bytes Free per Page.......................: 374.6 - Avg. Page Density (full)....................: 95.37% |
通過分析這些結果可以知道該表的索引是否需要重構。下邊描述了每一行的意義描述
Pages Scanned表或索引中的長頁數
Extents Scanned表或索引中的長區頁數
Extent Switches DBCC遍歷頁時從一個區域到另一個區域的次數
Avg. Pages per Extent 相關區域中的頁數
Scan DensityBest Count是連續鏈接時的理想區
[Best Count:Actual Count]域改變數,Actual Count是實際區域改變數,Scan Density爲100%,表示沒有分塊。
Logical Scan Fragmentation掃描索引頁中失序頁的百分比
Extent Scan Fragmentation 不實際相鄰和包含鏈路中所有鏈接頁的區域數
Avg. Bytes Free per Page掃描頁面中平均自由字節數
Avg. Page Density (full) 平均頁密度,表示頁有多滿
從上面命令的執行結果可以看的出來,Best count爲3 而Actual Count爲5這表明orders表有分塊需要重構表索引。
三、重構索引的方法
<1>重構單個表,
DBCC DBREINDEX 重建指定數據庫中表的一個或多個索引。
語法
DBCC DBREINDEX
( [ 'database.owner.table_name'
[ , index_name
[ , fillfactor ]
]
]
) [ WITH NO_INFOMSGS ]
語法見SQL Server幫助。
比如:重構一個表,執行DBCC DBREINDEX(’表名’)
以northwind庫的orders表爲例,
dbcc dbreindex('northwind.dbo.orders')
dbcc showcontig('northwind.dbo.orders'),顯示結果如下,
DBCC SHOWCONTIG scanning 'Orders' table... Table: 'Orders' (21575115); index ID: 1, database ID: 6 TABLE level scan performed. - Pages Scanned................................: 22 - Extents Scanned..............................: 3 - Extent Switches..............................: 2 - Avg. Pages per Extent........................: 7.3 - Scan Density [Best Count:Actual Count].......: 100.00% [3:3] - Logical Scan Fragmentation ..................: 0.00% - Extent Scan Fragmentation ...................: 33.33% - Avg. Bytes Free per Page.....................: 869.2 - Avg. Page Density (full).....................: 89.26%
|
通過結果我們可以看到Scan Denity爲100%表沒有分塊不需要重構表索引了。
<2>重構一個庫中的所有表,
use 庫名
sp_msforeachtable 'dbcc DBREINDEX("?")'
sp_msforeachtable表示對庫中每一個表執行某一條命令,相當於一個循環,執行完後,所有的表的索引都被重構;
<3>整體重構 DBCC CHECKDB;
DBCC CHECKDB ('pubs',repair_rebuild)
DBCC CHECKDB 不僅僅會修復索引,檢查指定數據庫中的所有對象的分配和結構完整性。
對於數據庫中每個表,DBCC CHECKDB 檢查其:
1.索引和數據頁是否已正確鏈接。
2.索引是否按照正確的順序排列。
3.各指針是否一致。
4.每頁上的數據是否均合理。
5.頁面偏移量是否合理。
組合命令如下:
<1>將數據庫置爲單用戶模式;
sp_dboption 庫名, single, true
<2>對整個庫進行重構;
DBCC CHECKDB('庫名',repair_rebuild)
附註:如果想對單個表進行重構,
DBCC CHECKTABLE(Authors, REPAIR_REBUILD )
<3>將數據庫置爲多用戶模式;
sp_dboption zrb, single, false
注意:
DBCC CHECKDB 是大量佔用 CPU 和磁盤的操作。每一個需要檢查的數據頁都必須首先從磁盤讀入內存。另外,DBCC CHECKDB 使用 tempdb 排序。
如果在 DBCC CHECKDB 運行時動態執行事務,那麼事務日誌會繼續增長,因爲 DBCC 命令在完成日誌的讀取之前阻塞日誌截斷。
建議在服務器負荷較少的時候運行 DBCC CHECKDB。如果在負荷高峯期運行 DBCC CHECKDB,那麼事務吞吐量性能和 DBCC CHECKDB 完成時間性能都會受到影響。
四、定時重構,
如果數據庫訪問非常頻繁的話,非常容易出現數據分塊的現象,因此可以利用作業來系統相對空閒的時候重構索引。