DBCC SHOWCONTIG (Transact-SQL)

Muestra información sobre la fragmentación de los datos y los índices de la tabla o vista especificada.

Nota importanteImportante

Esta característica se quitará en una versión futura de Microsoft SQL Server. No utilice esta característica en nuevos trabajos de desarrollo y modifique lo antes posible las aplicaciones que actualmente la utilizan. Utilice sys.dm_db_index_physical_stats en su lugar.

Icono de vínculo a temasConvenciones de sintaxis de Transact-SQL

Sintaxis

DBCC SHOWCONTIG 
[ ( 
    { table_name | table_id | view_name | view_id } 
    [ , index_name | index_id ] 
) ] 
    [ WITH 
        { 
         [ , [ ALL_INDEXES ] ] 
         [ , [ TABLERESULTS ] ] 
         [ , [ FAST ] ]
         [ , [ ALL_LEVELS ] ] 
         [ NO_INFOMSGS ]
         }
    ]

Argumentos

  • table_name | table_id | view_name | view_id
    Es la tabla o vista cuya información de fragmentación se va a comprobar. Si no se especifica, se comprueban todas las tablas y vistas indizadas de la base de datos actual. Para obtener el Id. de la tabla o la vista, utilice la función OBJECT_ID.

  • index_name | index_id
    Es el índice cuya información de fragmentación se va a comprobar. Si no se especifica, la instrucción procesa el índice base de la tabla o la vista especificada. Para obtener el Id. del índice, utilice la vista de catálogo sys.indexes.

  • WITH
    Especifica las opciones del tipo de información que devuelve la instrucción DBCC.

  • FAST
    Especifica si se realiza un examen rápido del índice y se ofrece la mínima información de salida. Un examen rápido no lee las páginas de nivel de datos u hoja del índice.

  • ALL_INDEXES
    Muestra el resultado de todos los índices para las tablas y vistas especificadas, aunque se haya especificado un índice determinado.

  • TABLERESULTS
    Muestra el resultado como un conjunto de filas, con información adicional.

  • ALL_LEVELS
    Se mantiene únicamente por compatibilidad con versiones anteriores. Aunque se especifique ALL_LEVELS, solo se procesa el nivel hoja de índice o el nivel de datos de tabla.

  • NO_INFOMSGS
    Suprime todos los mensajes informativos con niveles de gravedad entre 0 y 10.

Conjuntos de resultados

En la tabla siguiente se describe la información del conjunto de resultados.

Estadística

Descripción

Pages Scanned

Número de páginas de la tabla o el índice.

Extents ned

Número de extensiones de la tabla o el índice.

Extent Switches

Número de veces que la instrucción DBCC se ha movido de una extensión a otra al examinar las páginas de la tabla o el índice.

Avg. Pages per Extent

Número de páginas por extensión en la cadena de páginas.

Scan Density [Best Count: Actual Count]

Es un porcentaje. Es la relación entre Best Count y Actual Count. Este valor es 100 si todo es contiguo; si dicho valor es inferior a 100, existe fragmentación.

Best Count es el número ideal de cambios de extensión si todo está vinculado de forma contigua. Actual Count es el número real de cambios de extensión.

Logical Scan Fragmentation

Porcentaje de páginas que no funcionan resultante del examen de las páginas hoja del índice. Este número no es relevante para los montones. Una página no ordenada es aquella en la que la siguiente página física asignada al índice no es la que señala el puntero de página siguiente en la página hoja actual.

Extent Scan Fragmentation

Porcentaje de extensiones que no funcionan resultante del examen de las páginas hoja del índice. Este número no es relevante para los montones. Una extensión que no funciona es aquella en que la extensión que contiene la página actual de un índice no es físicamente la extensión siguiente a la que contiene la página anterior de un índice.

NotaNota
Este número carece de significado si el índice abarca varios archivos.

Avg. Bytes Free per Page

Valor promedio de los bytes libres de las páginas exploradas. Cuanto más alto es el número, menos llenas estarán las páginas. Los números más bajos funcionan mejor si el índice no contiene muchas inserciones aleatorias. Este número también está influido por el tamaño de la fila; un tamaño de fila grande puede provocar un número más alto.

Avg. Page density (full)

Promedio de densidad de página en porcentaje. Este valor tiene en cuenta el tamaño de la fila. Por consiguiente, dicho valor es una medida más precisa del grado de llenado de las páginas. Cuanto mayor sea el porcentaje, mejor.

Cuando se especifica table_id y FAST, DBCC SHOWCONTIG devuelve un conjunto de resultados con solo las siguientes columnas.

  • Pages Scanned

  • Extent Switches

  • Scan Density [Best Count:Actual Count]

  • Extent Scan Fragmentation

  • Logical Scan Fragmentation

Si se especifica TABLERESULTS, DBCC SHOWCONTIG devuelve las siguientes columnas además de las nueve columnas descritas en la tabla anterior.

Estadística

Descripción

Object Name

Nombre de la tabla o la vista procesada.

ObjectId

Id. del nombre del objeto.

IndexName

Nombre del índice procesado. Es NULL para un montón.

IndexId

Id. del índice. Es 0 para un montón.

Level

Nivel del índice. El nivel 0 es el nivel hoja o datos del índice.

Para un montón, Level es 0.

Pages

Número de páginas que componen el nivel del índice o de todo el montón.

Rows

Número de registros de datos o índices en este nivel del índice. Para un montón, este valor es el número de registros de datos en todo el montón.

Para un montón, es posible que el número de registros devueltos por esta función no coincida con el número de filas devuelto al ejecutar SELECT COUNT(*) contra el montón. Esto es debido a que una fila puede contener varios registros. Por ejemplo, en algunas situaciones de una actualización, una única fila del montón puede tener un registro de reenvío y un registro reenviado como resultado de la actualización. Asimismo, la mayoría de las filas LOB de gran tamaño se dividen en varios registros en almacenamiento de LOB_DATA.

MinimumRecordSize

Tamaño mínimo del registro en el nivel de índice o en todo el montón.

MaximumRecordSize

Tamaño máximo del registro en el nivel del índice o en todo el montón.

AverageRecordSize

Promedio de tamaño del registro en el nivel de índice o en todo el montón.

ForwardedRecords

Número de registros reenviados en el nivel de índice o en todo el montón.

Extents

Número de extensiones en el nivel de índice o en todo el montón.

ExtentSwitches

Número de veces que la instrucción DBCC se ha movido de una extensión a otra al examinar las páginas de la tabla o el índice.

AverageFreeBytes

Valor promedio de los bytes libres de las páginas exploradas. Cuanto más alto es el número, menos llenas estarán las páginas. Los números más bajos funcionan mejor si el índice no contiene muchas inserciones aleatorias. Este número también está influido por el tamaño de la fila; un tamaño de fila grande puede provocar un número más alto.

AveragePageDensity

Promedio de densidad de página en porcentaje. Este valor tiene en cuenta el tamaño de la fila. Por consiguiente, dicho valor es una medida más precisa del grado de llenado de las páginas. Cuanto mayor sea el porcentaje, mejor.

ScanDensity

Es un porcentaje. Es la relación entre BestCount y ActualCount. Este valor es 100 si todo es contiguo; si dicho valor es inferior a 100, existe fragmentación.

BestCount

Es el número idóneo de cambios de extensión si todo está vinculado de forma contigua.

ActualCount

Es el número real de cambios de extensión.

LogicalFragmentation

Porcentaje de páginas que no funcionan resultante del examen de las páginas hoja del índice. Este número no es relevante para los montones. Una página no ordenada es aquella en la que la siguiente página física asignada al índice no es la que señala el puntero de página siguiente en la página hoja actual.

ExtentFragmentation

Porcentaje de extensiones que no funcionan resultante del examen de las páginas hoja del índice. Este número no es relevante para los montones. Una extensión que no funciona es aquella en que la extensión que contiene la página actual de un índice no es físicamente la extensión siguiente a la que contiene la página anterior de un índice.

NotaNota
Este número carece de significado si el índice abarca varios archivos.

Cuando se especifican WITH TABLERESULTS y FAST, el conjunto de resultados es el mismo que cuando se especifica WITH TABLERESULTS, con la diferencia de que las siguientes columnas tendrán valores NULL:

Rows

Extents

MinimumRecordSize

AverageFreeBytes

MaximumRecordSize

AveragePageDensity

AverageRecordSize

ExtentFragmentation

ForwardedRecords

 

Comentarios

Cuando se especifica index_id, la instrucción DBCC SHOWCONTIG recorre la cadena de páginas en el nivel hoja del índice especificado. Si solo se especifica table_id o si index_id es 0, se examinan las páginas de datos de la tabla especificada. Esta operación solo requiere un bloqueo de tabla con intención compartida (IS). De este modo, se pueden realizar todas las actualizaciones e inserciones excepto las que requieren un bloqueo de tabla exclusivo (X). Esto permite un equilibrio entre la velocidad de ejecución y la no reducción de la simultaneidad con respecto al número de estadísticas devueltas. No obstante, si el comando se va a utilizar solo para medir la fragmentación, se recomienda utilizar la opción WITH FAST para que el rendimiento sea óptimo. Un examen rápido no lee las páginas de nivel de datos u hoja del índice. La opción WITH FAST no se aplica a un montón.

El algoritmo para calcular la fragmentación es más preciso en SQL Server 2008 y versiones posteriores que en SQL Server 2000. En consecuencia, los valores de fragmentación aparecerán mayores. Por ejemplo, en SQL Server 2000, no se considera que una tabla está fragmentada si tiene las páginas 11 y 13 en la misma extensión y no la página 12. Sin embargo, el acceso a estas dos páginas requeriría dos operaciones de E/S físicas, por lo que en SQL Server 2008 esto se considera fragmentación.

Restricciones

DBCC SHOWCONTIG no muestra los datos con los tipos de datos ntext, text e image Esto se debe a que ya no existen los índices de texto (Id. de índice 255 en SQL Server 2000) que almacenan datos de texto e imagen. Para obtener más información acerca del Id. de índice 255, vea sys.sysindexes (Transact-SQL).

Además, DBCC SHOWCONTIG no admite algunas características nuevas. Por ejemplo:

  • Si la tabla o el índice especificados tienen particiones, DBCC SHOWCONTIG solo muestra la primera partición de la tabla o el índice especificados.

  • DBCC SHOWCONTIG no muestra la información de almacenamiento de desbordamiento de fila y otros tipos de datos no consecutivos nuevos como nvarchar(max), varchar(max), varbinary(max) y xml.

  • DBCC SHOWCONTIG no admite los índices espaciales.

Todas las características nuevas son totalmente compatibles con la vista de administración dinámica sys.dm_db_index_physical_stats (Transact-SQL).

Fragmentación de tablas

DBCC SHOWCONTIG determina si la tabla está muy fragmentada. La fragmentación de las tablas es consecuencia de los procesos de modificación de los datos (instrucciones INSERT, UPDATE y DELETE) efectuados en las tablas. Como dichas modificaciones no suelen estar distribuidas de forma equilibrada entre todas las filas de la tabla, el llenado de cada página puede variar con el paso del tiempo. En las consultas que examinan la totalidad o parte de una tabla, esta fragmentación de tabla puede ocasionar lecturas de páginas adicionales. Esto afecta al examen paralelo de los datos.

Cuando un índice está muy fragmentado, existen dos opciones para reducir la fragmentación:

  • Quite y vuelva a crear un índice clúster.

    La reconstrucción de un índice clúster reorganiza los datos y hace que las páginas de datos se llenen. El grado de llenado se puede configurar mediante la opción FILLFACTOR en CREATE INDEX. El inconveniente de este método es que el índice está sin conexión durante el proceso de eliminación y nueva creación, y que la operación es atómica. Si se interrumpe la creación del índice, éste no se vuelve a crear.

  • Reordene las páginas de nivel hoja del índice en un orden lógico.

    Utilice ALTER INDEX…REORGANIZE para reordenar las páginas de nivel hoja del índice en un orden lógico. Dado que esta operación se realiza en línea, el índice está disponible mientras se ejecuta la instrucción. También es posible interrumpir la operación sin perder todo el trabajo. El inconveniente de este método es que no es una forma tan buena de reorganizar los datos como la operación de quitar y volver a crear el índice clúster.

  • Vuelve a generar el índice.

    Para volver a generar el índice, utilice ALTER INDEX con REBUILD. Para obtener más información, vea ALTER INDEX (Transact-SQL).

Avg. Bytes free per page y Avg. Page density (full) del conjunto de resultados indican el llenado de las páginas de índice. Avg. Bytes free per page debe ser bajo y Avg. Page density (full) debe ser alto para un índice que no tenga muchas inserciones aleatorias. Quitar y volver a crear un índice con la opción FILLFACTOR especificada puede mejorar estas estadísticas. Además, ALTER INDEX con REORGANIZE compactará un índice, teniendo en cuenta FILLFACTOR, lo que mejorará las estadísticas.

Nota

En un índice que contenga muchas inserciones aleatorias y páginas muy llenas se produce un aumento de las divisiones de páginas. Esto aumenta a su vez la fragmentación.

El nivel de fragmentación de un índice puede determinarse de las siguientes formas:

  • Mediante la comparación de los valores de Extent Switches y Extents Scanned.

    El valor de Extent Switches debe ser lo más parecido posible al de Extents Scanned. Esta relación se calcula como el valor de Scan Density. Dicho valor debe ser lo más alto posible y se puede aumentar mediante la reducción de la fragmentación del índice.

    Nota

    Este método no funciona si el índice abarca varios archivos.

  • Mediante la comprensión de los valores de Logical Scan Fragmentation y Extent Scan Fragmentation.

    El valor de Logical Scan Fragmentation y, en menor medida, el valor de Extent Scan Fragmentation ofrecen la mejor indicación del nivel de fragmentación de una tabla. Ambos valores deberían tender a cero tanto como fuera posible, aunque puede ser aceptable un valor entre el 0 y el 10 por ciento.

    Nota

    El valor de Extent Scan Fragmentation es alto si el índice abarca varios archivos. Para reducir estos valores, debe reducir la fragmentación del índice.

Permisos

El usuario debe ser propietario de la tabla o ser un miembro del rol fijo de servidor sysadmin o de los roles fijos de base de datos db_owner o db_ddladmin.

Ejemplos

A. Presentar la información de fragmentación de una tabla

En el siguiente ejemplo se muestra la información de fragmentación para la tabla Employee.

USE AdventureWorks2008R2;
GO
DBCC SHOWCONTIG ("HumanResources.Employee");
GO

B. Usar OBJECT_ID para obtener el Id. de la tabla y sys.indexes para obtener el Id. del índice

En el siguiente ejemplo se utiliza OBJECT_ID y la vista de catálogo sys.indexes para obtener el Id. de tabla y el Id. de índice para el índice AK_Product_Name de la tabla Production.Product en la base de datos AdventureWorks2008R2.

USE AdventureWorks2008R2;
GO
DECLARE @id int, @indid int
SET @id = OBJECT_ID('Production.Product')
SELECT @indid = index_id 
FROM sys.indexes
WHERE object_id = @id 
   AND name = 'AK_Product_Name'
DBCC SHOWCONTIG (@id, @indid);
GO

C. Mostrar un conjunto de resultados resumido de una tabla

En el siguiente ejemplo se devuelve un conjunto de resultados resumido para la tabla Product de la base de datos AdventureWorks2008R2.

USE AdventureWorks2008R2;
GO
DBCC SHOWCONTIG ("Production.Product", 1) WITH FAST;
GO

D. Mostrar el conjunto de resultados completo para todos los índices de todas las tablas de la base de datos

En el siguiente ejemplo se devuelve un conjunto de resultados de tabla completo para todos los índices de todas las tablas de la base de datos AdventureWorks2008R2 .

USE AdventureWorks2008R2;
GO
DBCC SHOWCONTIG WITH TABLERESULTS, ALL_INDEXES;
GO

E. Usar DBCC SHOWCONTIG y DBCC INDEXDEFRAG para desfragmentar los índices de una base de datos

En el siguiente ejemplo se muestra una forma sencilla de desfragmentar todos los índices de una base de datos que está fragmentada por encima de un umbral declarado.

/*Perform a 'USE <database name>' to select the database in which to run the script.*/
-- Declare variables
SET NOCOUNT ON;
DECLARE @tablename varchar(255);
DECLARE @execstr   varchar(400);
DECLARE @objectid  int;
DECLARE @indexid   int;
DECLARE @frag      decimal;
DECLARE @maxfrag   decimal;

-- Decide on the maximum fragmentation to allow for.
SELECT @maxfrag = 30.0;

-- Declare a cursor.
DECLARE tables CURSOR FOR
   SELECT TABLE_SCHEMA + '.' + 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 the cursor for the 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