Sunday, January 26, 2014

DBCC SHOWCONTIG was replaced by sys.dm_db_index_physical_stats

DBCC SHOWCONTIG is used to return table/index fragmentation information.  It is a deprecated feature, but it hasn't been discontinued yet.  You can still run it in v2012, but it is recommended to use the replacement DMV, sys.dm_db_index_physical_stats.  In this post I am going to show you a sample use of both features. 

We'll do SHOWCONTIG first.  You can create the 'Fragmentation' table as a permanent table, or #temporary table, but I have used a perm table in my sample.

#1 -- DBCC SHOWCONTIG

/* To store your table results. */
CREATE TABLE [dbo].[Fragmentation](
  ObjectName CHAR (255),
  ObjectId INT,
  IndexName CHAR (255),
  IndexId INT,
  Level 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
) ON [YourDatabase_Data]
GO

/* Run the SHOWCONTIG */   
SET NOCOUNT ON;

DECLARE
  @tablename VARCHAR (128),
  @tableschema VARCHAR (128),
  @execstr VARCHAR (255),
  @objectid INT,
  @IndexName VARCHAR (255),
  @frag DECIMAL,
  @maxfrag DECIMAL
 
  /* Declare your cursor */
  DECLARE tables CURSOR
  FAST_FORWARD
  FOR
     SELECT TABLE_NAME, TABLE_SCHEMA
     FROM INFORMATION_SCHEMA.TABLES
     WHERE TABLE_TYPE = 'BASE TABLE'

  /* Open your cursor */
  OPEN tables

  /* Loop through all the tables in your database */
  FETCH NEXT
  FROM tables
  INTO @tablename, @tableschema

  WHILE @@FETCH_STATUS = 0
  BEGIN
     /* Perform DBCC SHOWCONTIG for all indices of the table. */
     SELECT @tablename = @tableschema + '.' + @tablename
     INSERT INTO YourDatabase.dbo.Fragmentation --- Writing to your Fragmentation table
     EXEC ('DBCC SHOWCONTIG (''' + @tablename + ''') WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS')
     FETCH NEXT
     FROM tables
     INTO @tablename, @tableschema
  END

  /* Close and deallocate your cursor */
  CLOSE tables
  DEALLOCATE tables

  /* Review the index statistics */ 

SELECT * FROM YourDatabase.dbo.Fragmentation

SET NOCOUNT OFF;
 


#2 -- sys.dm_db_index_physical_stats

Now we'll use the DMV.  We'll return the index statistics for ALL user tables.  You will see in our WHERE clause we are looking for fragmentation greater than 30%, and we are excluding the HEAPs.


 
/* Use sys.dm_db_index_physical_stats */
SELECT
    SCHEMA_NAME(t.schema_id) [SchemaName],
    OBJECT_NAME(ps.object_id) [TableName],
    i.name [IndexName],
    ps.Index_type_desc [IndexType],
    CONVERT(TINYINT,ps.avg_fragmentation_in_percent) [AvgFrag%],
    CONVERT(TINYINT,ps.avg_page_space_used_in_percent) [AvgSpaceUsed%],
    ps.record_count [RecordCount],
    ps.fragment_count [FragmentCount]
FROM  
    sys.dm_db_index_physical_stats(db_id(db_name()),NULL,NULL,NULL,'DETAILED') ps INNER JOIN sys.indexes i
     ON ps.object_id = i.object_id
     AND ps.index_id = i.index_id INNER JOIN sys.tables t 
       ON ps.object_id = t.object_id
WHERE
    avg_fragmentation_in_percent > 30.0
    AND ps.index_id > 0

ORDER BY
    [SchemaName],
    [TableName],
    [IndexName]


IMPORTANT NOTE:  You may use SAMPLED, LIMITED or DETAILED in the call to sys.dm_db_index_physical_stats.  This is referred to as the 'scanning mode', and it dictates the level of scanning that is performed, AND how much time the process will take.  See here for more information:     http://technet.microsoft.com/en-us/library/ms188917.aspx

No comments:

Post a Comment