顯示指定的表的數(shù)據(jù)和索引的碎片信息。
DBCC SHOWCONTIG
[ ( { table_name | table_id | view_name | view_id }
[ , index_name | index_id ]
)
]
[ WITH { ALL_INDEXES
| FAST [ , ALL_INDEXES ]
| TABLERESULTS [ , { ALL_INDEXES } ]
[ , { FAST | ALL_LEVELS } ]
}
]
table_name | table_id | view_name | view_id
是要對其碎片信息進(jìn)行檢查的表或視圖。如果未指定,則對當(dāng)前數(shù)據(jù)庫中的所有表和索引視圖進(jìn)行檢查。若要獲得表或視圖 ID,請使用 OBJECT_ID 函數(shù)。
index_name | index_id
是要對其碎片信息進(jìn)行檢查的索引。如果未指定,則該語句對指定表或視圖的基索引進(jìn)行處理。若要獲得索引 ID,請使用 sysindexes。
WITH
指定由 DBCC 語句所返回的信息類型選項(xiàng)。
FAST
指定是否要對索引執(zhí)行快速掃描和輸出最少信息。快速掃描不讀取索引的葉或數(shù)據(jù)級頁。
TABLERESULTS
將結(jié)果顯示為帶有附加信息的行集。
ALL_INDEXES
顯示指定表和視圖的所有索引的結(jié)果(即使指定特定的索引)。
ALL_LEVELS
只能與 TABLERESULTS 選項(xiàng)一起使用。不能與 FAST 選項(xiàng)一起使用。指定是否為所處理的每個索引的每個級別產(chǎn)生輸出。如果未指定,將只對索引葉級或表數(shù)據(jù)級進(jìn)行處理。
當(dāng)指定 index_id 時,DBCC SHOWCONTIG 語句將遍歷指定索引的葉級上的頁鏈。如果只指定 table_id,或者如果 index_id 為 0,則對指定表的數(shù)據(jù)頁進(jìn)行掃描。
DBCC SHOWCONTIG 確定表是否高度碎片化。在對表進(jìn)行數(shù)據(jù)修改(INSERT、UPDATE 和 DELETE 語句)的過程中會出現(xiàn)表碎片現(xiàn)象。由于這些修改通常并不在表的行中進(jìn)行平均分布,所以每頁的填滿狀態(tài)會隨時間而改變。對于掃描部分或全部表的查詢,這些表碎片會導(dǎo)致額外的頁讀取,這將防礙數(shù)據(jù)的并行掃描。
當(dāng)索引的碎片非常多時,有兩種減少碎片的方法:
重新創(chuàng)建聚集索引將對數(shù)據(jù)進(jìn)行重新組織,其結(jié)果是使數(shù)據(jù)頁填滿。填滿程度可以使用 FILLFACTOR 選項(xiàng)進(jìn)行配置。這種方法的缺點(diǎn)是索引在除去/重新創(chuàng)建周期內(nèi)為脫機(jī)狀態(tài),并且操作屬原子級。如果中斷索引創(chuàng)建,則不會重新創(chuàng)建該索引。
DBCC INDEXDEFRAG 命令是聯(lián)機(jī)操作,所以索引只有在該命令正在運(yùn)行時才可用。而且可以在不丟失已完成工作的情況下中斷該操作。這種方法的缺點(diǎn)是在重新組織數(shù)據(jù)方面沒有聚集索引的除去/重新創(chuàng)建操作有效。
結(jié)果集中的"每頁上的平均可用字節(jié)數(shù)"和"平均頁密度(完整)"統(tǒng)計量指出索引頁的飽滿程度。"每頁上的平均可用字節(jié)數(shù)"的數(shù)字應(yīng)較小,而"平均頁密度(完整)"的數(shù)字應(yīng)較大。在指定 FILLFACTOR 選項(xiàng)的情況下除去和重新創(chuàng)建聚集索引可改善這些統(tǒng)計。另外,DBCC INDEXDEFRAG 命令在壓縮索引時考慮其 FILLFACTOR,這將改善這些統(tǒng)計。
索引的碎片級可以兩種方式確定:
注意:如果索引跨多個文件,這種確定碎片的方法不起作用。"擴(kuò)展盤區(qū)開關(guān)數(shù)"的值應(yīng)盡可能接近于"掃描擴(kuò)展盤區(qū)數(shù)"的值。算出這一比率作為"掃描密度"的值,該值應(yīng)盡可能高。通過前面討論的減少碎片的任一種方法可改善該值。
"邏輯掃描碎片"和"擴(kuò)展盤區(qū)掃描碎片"(對于較小的擴(kuò)展盤區(qū))的值很好地表明了表的碎片級。這些值應(yīng)盡可能接近零(但 0% 到 10% 的值也可接受)。需要注意的是,如果索引跨多個文件,則"擴(kuò)展盤區(qū)掃描碎片"的值較大。兩種減少碎片的方法都可用于減少這些值。
下表描述結(jié)果集內(nèi)的信息。
統(tǒng)計 | 描述 |
---|---|
掃描頁數(shù) | 表或索引的頁數(shù)。 |
掃描擴(kuò)展盤區(qū)數(shù) | 表或索引中的擴(kuò)展盤區(qū)數(shù)。 |
擴(kuò)展盤區(qū)開關(guān)數(shù) | 遍歷索引或表的頁時,DBCC 語句從一個擴(kuò)展盤區(qū)移動到其它擴(kuò)展盤區(qū)的次數(shù)。 |
平均擴(kuò)展盤區(qū)上的平均頁數(shù) | 頁鏈中每個擴(kuò)展盤區(qū)的頁數(shù)。 |
掃描密度 [最佳值:實(shí)際值] | 最佳值是指在一切都連續(xù)地鏈接的情況下,擴(kuò)展盤區(qū)更改的理想數(shù)目。實(shí)際值是指擴(kuò)展盤區(qū)更改的實(shí)際次數(shù)。如果一切都連續(xù),則掃描密度數(shù)為 100;如果小于 100,則存在碎片。掃描密度為百分比值。 |
邏輯掃描碎片 | 對索引的葉級頁掃描所返回的無序頁的百分比。該數(shù)與堆集和文本索引無關(guān)。無序頁是指在 IAM 中所指示的下一頁不同于由葉級頁中的下一頁指針?biāo)赶虻捻摗?/TD> |
擴(kuò)展盤區(qū)掃描碎片 | 無序擴(kuò)展盤區(qū)在掃描索引葉級頁中所占的百分比。該數(shù)與堆集無關(guān)。無序擴(kuò)展盤區(qū)是指:含有索引的當(dāng)前頁的擴(kuò)展盤區(qū)不是物理上的含有索引的前一頁的擴(kuò)展盤區(qū)后的下一個擴(kuò)展盤區(qū)。 |
平均每頁上的平均可用字節(jié)數(shù) | 所掃描的頁上的平均可用字節(jié)數(shù)。數(shù)字越大,頁的填滿程度越低。數(shù)字越小越好。該數(shù)還受行大小影響:行大小越大,數(shù)字就越大。 |
平均頁密度(完整) | 平均頁密度(為百分比)。該值考慮行大小,所以它是頁的填滿程度的更準(zhǔn)確表示。百分比越大越好。 |
如果指定表 ID 和 FAST 選項(xiàng),DBCC SHOWCONTIG 將返回僅包含以下列的結(jié)果集:
如果指定 TABLERESULTS,DBCC SHOWCONTIG 將返回在第一個表中描述的 8 列和以下的附加列。
統(tǒng)計 | 描述 |
---|---|
ObjectName | 處理的表或視圖的名稱。 |
ObjectId | 對象名 ID。 |
IndexName | 處理的索引名。堆集的 IndexName 為 NULL。 |
IndexId | 索引的 ID。堆集的 IndexId 為 0。 |
Level | 索引的級別。級別 0 是索引的葉(或數(shù)據(jù))級。級別數(shù)隨著沿樹向上移動到索引根而增加。堆集的級別為 0。 |
Pages | 組成某個索引級或整個堆集的頁數(shù)。 |
Rows | 某個索引級上的數(shù)據(jù)或索引記錄數(shù)。對于堆集,這是整個堆集中的數(shù)據(jù)記錄數(shù)。 |
MinimumRecordSize | 某個索引級或整個堆集中的最小記錄大小。 |
MaximumRecordSize | 某個索引級或整個堆集中的最大記錄大小。 |
AverageRecordSize | 某個索引級或整個堆集中的平均記錄大小。 |
ForwardedRecords | 某個索引級或整個堆集中的轉(zhuǎn)發(fā)記錄數(shù)。 |
Extents | 某個索引級或整個堆集中的擴(kuò)展盤區(qū)數(shù)。 |
指定 TABLERESULTS 和 FAST 時,DBCC SHOWCONTIG 將返回如下列。
DBCC SHOWCONTIG 權(quán)限默認(rèn)授予 sysadmin 固定服務(wù)器角色或 db_owner 和 db_ddladmin 固定數(shù)據(jù)庫角色的成員以及表的所有者且不可轉(zhuǎn)讓。
下例顯示帶指定表名的表的碎片信息。
USE Northwind
GO
DBCC SHOWCONTIG (Employees)
GO
下例使用 OBJECT_ID 和 sysindexes 獲得 authors 表的 aunmind 索引的表 ID 和索引 ID。
USE pubs
GO
DECLARE @id int, @indid int
SET @id = OBJECT_ID('authors')
SELECT @indid = indid
FROM sysindexes
WHERE id = @id
AND name = 'aunmind'
DBCC SHOWCONTIG (@id, @indid)
GO
下例返回 pubs 數(shù)據(jù)庫中 authors 表的簡略結(jié)果集。
USE pubs
DBCC SHOWCONTIG ('authors', 1) WITH FAST
下例顯示 pubs 數(shù)據(jù)庫中每個表上的每個索引的完整表結(jié)果集。
USE pubs
DBCC SHOWCONTIG WITH TABLERESULTS, ALL_INDEXES
下例顯示對數(shù)據(jù)庫中碎片數(shù)量在聲明的閾值之上的所有索引進(jìn)行碎片整理的簡單方法。
/*Perform a 'USE <database name>' to select the database in which to run the script.*/相關(guān)文章
-- Declare variables
SET NOCOUNT ON
DECLARE @tablename VARCHAR (128)
DECLARE @execstr VARCHAR (255)
DECLARE @objectid INT
DECLARE @indexid INT
DECLARE @frag DECIMAL
DECLARE @maxfrag DECIMAL
-- Decide on the maximum fragmentation to allow
SELECT @maxfrag = 30.0
-- Declare cursor
DECLARE tables CURSOR FOR
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
-- Create the table
CREATE TABLE #fraglist (
ObjectName CHAR (255),
ObjectId INT,
IndexName CHAR (255),
IndexId INT,
Lvl INT,
CountPages INT,
CountRows INT,
MinRecSize INT,
MaxRecSize INT,
AvgRecSize INT,
ForRecCount INT,
Extents INT,
ExtentSwitches INT,
AvgFreeBytes INT,
AvgPageDensity INT,
ScanDensity DECIMAL,
BestCount INT,
ActualCount INT,
LogicalFrag DECIMAL,
ExtentFrag DECIMAL)
-- Open the cursor
OPEN tables
-- Loop through all the tables in the database
FETCH NEXT
FROM tables
INTO @tablename
WHILE @@FETCH_STATUS = 0
BEGIN
-- Do the showcontig of all indexes of the table
INSERT INTO #fraglist
EXEC ('DBCC SHOWCONTIG (''' + @tablename + ''')
WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS')
FETCH NEXT
FROM tables
INTO @tablename
END
-- Close and deallocate the cursor
CLOSE tables
DEALLOCATE tables
-- Declare cursor for list of indexes to be defragged
DECLARE indexes CURSOR FOR
SELECT ObjectName, ObjectId, IndexId, LogicalFrag
FROM #fraglist
WHERE LogicalFrag >= @maxfrag
AND INDEXPROPERTY (ObjectId, IndexName, 'IndexDepth') > 0
-- Open the cursor
OPEN indexes
-- loop through the indexes
FETCH NEXT
FROM indexes
INTO @tablename, @objectid, @indexid, @frag
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'Executing DBCC INDEXDEFRAG (0, ' + RTRIM(@tablename) + ',
' + RTRIM(@indexid) + ') - fragmentation currently '
+ RTRIM(CONVERT(varchar(15),@frag)) + '%'
SELECT @execstr = 'DBCC INDEXDEFRAG (0, ' + RTRIM(@objectid) + ',
' + RTRIM(@indexid) + ')'
EXEC (@execstr)
FETCH NEXT
FROM indexes
INTO @tablename, @objectid, @indexid, @frag
END
-- Close and deallocate the cursor
CLOSE indexes
DEALLOCATE indexes
-- Delete the temporary table
DROP TABLE #fraglist
GO