This script will display fragmentation info on every index in a specified table.
-- ShowIndexFragmentation.sql SET NOCOUNT ON -- Set variables. DECLARE @sDatabase sysname SET @sDatabase = 'YourDB' -- Change this to your database! DECLARE @sTableName sysname SET @sTableName = 'YourTable' -- Change this to your table! DECLARE @sCmd NVARCHAR(4000) SET @sCmd = '' -- Create temp table. IF OBJECT_ID('tempdb..#ShowContigRaw') IS NOT NULL DROP TABLE #ShowContigRaw CREATE TABLE #ShowContigRaw ( TableName 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 DECIMAL(38,14), ScanDensity INT, BestCount INT, ActualCount INT, LogicalFrag DECIMAL(38,14), ExtentFrag DECIMAL(38,14) ) -- Call DBCC SHOWCONTIG on all indexes on the table to populate the temp table. SET @sCmd = 'USE ' + @sDatabase + ' DBCC SHOWCONTIG (''' + @sTableName + ''') WITH TABLERESULTS, ALL_INDEXES, NO_INFOMSGS' RAISERROR(@sCmd, 10, 1) WITH NOWAIT INSERT INTO #ShowContigRaw EXEC(@sCmd) -- Create temp table. IF OBJECT_ID('tempdb..#ShowContigCooked') IS NOT NULL DROP TABLE #ShowContigCooked CREATE TABLE #ShowContigCooked ( TableName NVARCHAR(255), -- Table Name ObjectId NVARCHAR(255), -- Object ID IndexName NVARCHAR(255), -- Index Name IndexId NVARCHAR(255), -- Index ID Lvl NVARCHAR(255), -- Level CountPages NVARCHAR(255), -- Page Count CountRows NVARCHAR(255), -- Row Count MinRecSize NVARCHAR(255), -- Min Row Size MaxRecSize NVARCHAR(255), -- Max Row Size AvgRecSize NVARCHAR(255), -- Avg Row Size ForRecCount NVARCHAR(255), -- Forwarded Record Count Extents NVARCHAR(255), -- Extent Count ExtentSwitches NVARCHAR(255), -- Extent Switches AvgFreeBytes NVARCHAR(255), -- AvgFreeBytes AvgPageDensity NVARCHAR(255), -- Avg Page Density ScanDensity NVARCHAR(255), -- Extent Contiguousness aka Scan Density BestCount NVARCHAR(255), -- Extent Changes Best Count ActualCount NVARCHAR(255), -- Extent Changes Actual Count LogicalFrag NVARCHAR(255), -- Logical Fragmentation ExtentFrag NVARCHAR(255) -- Extent Fragmentation ) INSERT INTO #ShowContigCooked SELECT * FROM #ShowContigRaw -- Massage values. UPDATE #ShowContigCooked SET TableName = RTRIM(TableName) UPDATE #ShowContigCooked SET IndexName = 'N/A' WHERE IndexName = '' UPDATE #ShowContigCooked SET IndexName = RTRIM(IndexName) UPDATE #ShowContigCooked SET CountPages = REPLACE(CONVERT(NVARCHAR, CONVERT(MONEY, CountPages), 1), '.00', '') UPDATE #ShowContigCooked SET CountRows = REPLACE(CONVERT(NVARCHAR, CONVERT(MONEY, CountRows), 1), '.00', '') UPDATE #ShowContigCooked SET MinRecSize = REPLACE(CONVERT(NVARCHAR, CONVERT(MONEY, MinRecSize), 1), '.00', '') UPDATE #ShowContigCooked SET MaxRecSize = REPLACE(CONVERT(NVARCHAR, CONVERT(MONEY, MaxRecSize), 1), '.00', '') UPDATE #ShowContigCooked SET AvgRecSize = REPLACE(CONVERT(NVARCHAR, CONVERT(MONEY, AvgRecSize), 1), '.00', '') UPDATE #ShowContigCooked SET ForRecCount = REPLACE(CONVERT(NVARCHAR, CONVERT(MONEY, ForRecCount), 1), '.00', '') UPDATE #ShowContigCooked SET Extents = REPLACE(CONVERT(NVARCHAR, CONVERT(MONEY, Extents), 1), '.00', '') UPDATE #ShowContigCooked SET ExtentSwitches = REPLACE(CONVERT(NVARCHAR, CONVERT(MONEY, ExtentSwitches), 1), '.00', '') UPDATE #ShowContigCooked SET AvgPageDensity = CONVERT(NVARCHAR, CONVERT(MONEY, AvgPageDensity), 1) + '%' UPDATE #ShowContigCooked SET BestCount = REPLACE(CONVERT(NVARCHAR, CONVERT(MONEY, BestCount), 1), '.00', '') UPDATE #ShowContigCooked SET ActualCount = REPLACE(CONVERT(NVARCHAR, CONVERT(MONEY, ActualCount), 1), '.00', '') UPDATE #ShowContigCooked SET ScanDensity = CONVERT(NVARCHAR, CONVERT(MONEY, ScanDensity), 1) + '%' UPDATE #ShowContigCooked SET LogicalFrag = CONVERT(NVARCHAR, CONVERT(MONEY, LogicalFrag), 1) + '%' UPDATE #ShowContigCooked SET ExtentFrag = CONVERT(NVARCHAR, CONVERT(MONEY, ExtentFrag), 1) + '%' -- Done. Display results. SELECT 'Name of the table or view.' AS 'Table Name', 'OBJECT_ID of the table or view.' AS 'Object ID', 'Name of the index.' AS 'Index Name', 'ID of the index.' AS 'Index ID', 'Level of the index. Level 0 is the leaf (or data) level of the index. The level number increases moving up the tree toward the index root. Level is 0 for a heap.' AS 'Level', 'Number of pages comprising that level of the index or entire heap.' AS 'Page Count', 'Number of data or index records at that level of the index. For a heap, this is the number of data records in the entire heap.' AS 'Row Count', 'Minimum record size in that level of the index or entire heap.' AS 'Min Row Size', 'Maximum record size in that level of the index or entire heap.' AS 'Max Row Size', 'Average record size in that level of the index or entire heap.' AS 'Avg Row Size', 'On UPDATES, if there is insufficient space on the page to fit the new record, the record is moved to a new page, and a forwarding record is left in the original location to point to the new location.' AS 'Forwarded Record Count', 'Number of extents in that level of the index or entire heap.' AS 'Extent Count', 'Number of jumps from one extent to another while traversing all the pages.' AS 'Extent Switches', -- 'Average number of free bytes on the pages scanned. The higher the number, -- the less full the pages are. Lower numbers are better. This number is also -- affected by row size; a large row size can result in a higher number.' -- AS 'AvgFreeBytes', 'Measure of how full the pages are. The higher the percentage, the better.' AS 'Avg Page Density', '"BestCount" / "Actual count" Is 100% if all extents are contiguous; else, some fragmentation exists.' AS 'Extent Changes Best Count', 'The ideal number of extent changes if the extents are perfectly contiguous.' AS 'Extent Changes Actual Count', 'Actual number of extent changes while traversing.' AS 'Extent Contiguousness aka Scan Density', 'Percentage of out-of-order pages returned from scanning the leaf pages of an index. This number is not relevant to heaps and text indexes.' AS 'Logical Fragmentation', 'Percentage of out-of-order extents in scanning the leaf pages of an index. This number is not relevant to heaps.' AS 'Extent Fragmentation' UNION SELECT TableName AS 'Table Name', -- YourTable ObjectId AS 'Object ID', -- 613577224 IndexName AS 'Index Name', -- tank_data_index IndexId AS 'Index ID', -- 2 Lvl AS 'Level', -- 0 CountPages AS 'Page Count', -- 48,139 CountRows AS 'Row Count', -- 7,271,509 MinRecSize AS 'Min Row Size', -- 51 MaxRecSize AS 'Max Row Size', -- 61 AvgRecSize AS 'Avg Row Size', -- 51 ForRecCount AS 'Forwarded Record Count', -- 0 Extents AS 'Extent Count', -- 9,233 ExtentSwitches AS 'Extent Switches', -- 26,012 -- AvgFreeBytes AS 'AvgFreeBytes', AvgPageDensity AS 'Avg Page Density', -- 98% BestCount AS 'Extent Changes Best Count', -- 6,018 ActualCount AS 'Extent Changes Actual Count', -- 26,013 ScanDensity AS 'Scan Density', -- 23% LogicalFrag AS 'Logical Fragmentation', -- 19% ExtentFrag AS 'Extent Fragmentation' -- 70% FROM #ShowContigCooked WHERE TableName NOT LIKE 'dt%' AND TableName NOT LIKE 'sys%' ORDER BY 'Extent Fragmentation' DESC DROP TABLE #ShowContigCooked
0 comments:
Post a Comment