DBCC INDEXDEFRAG (Transact-SQL)

Si applica a: SQL Server Istanza gestita di SQL di Azure

Deframmenta gli indici della tabella o vista specificata.

Importante

Questa funzionalità verrà rimossa a partire da una delle prossime versioni di Microsoft SQL Server. Evitare di usare questa funzionalità in un nuovo progetto di sviluppo e prevedere interventi di modifica nelle applicazioni in cui è attualmente implementata. In alternativa, usare ALTER INDEX.

Si applica a: SQL Server 2008 (10.0.x) e versioni successive

Convenzioni della sintassi Transact-SQL

Sintassi

DBCC INDEXDEFRAG
(
    { database_name | database_id | 0 }
    , { table_name | table_id | view_name | view_id }
    [ , { index_name | index_id } [ , { partition_number | 0 } ] ]
)
    [ WITH NO_INFOMSGS ]

Nota

Per visualizzare la sintassi Transact-SQL per SQL Server 2014 e versioni precedenti, vedere Documentazione delle versioni precedenti.

Argomenti

database_name | database_id | 0

Database contenente l'indice da deframmentare. Se si specifica 0, viene utilizzato il database corrente. I nomi dei database devono essere conformi alle regole per gli identificatori.

table_name | table_id | view_name | view_id

Tabella o vista contenente l'indice da deframmentare. I nomi delle tabelle e delle viste devono essere conformi alle regole per gli identificatori.

index_name | index_id

Nome o ID dell'indice da deframmentare. Se viene omesso, l'istruzione deframmenta tutti gli indici della tabella o vista specificata. I nomi degli indici devono essere conformi alle regole per gli identificatori.

partition_number | 0

Numero di partizione dell'indice da deframmentare. Se non viene specificato o viene specificato 0, l'istruzione deframmenta tutte le partizioni nell'indice specificato.

WITH NO_INFOMSGS

Evita la visualizzazione di tutti i messaggi informativi con livello di gravità compreso tra 0 e 10.

Osservazioni

DBCC INDEXDEFRAG deframmenta il livello foglia di un indice in modo che l'ordine fisico delle pagine corrisponda all'ordine logico da sinistra a destra dei nodi foglia, migliorando quindi le prestazioni di analisi degli indici.

Nota

Quando DBCC INDEXDEFRAG viene eseguita, la deframmentazione dell'indice viene eseguita in modo seriale. Ciò significa che l'operazione su un indice singolo viene eseguita tramite un thread singolo, senza parallelismo. Inoltre, le operazioni su più indici della stessa DBCC INDEXDEFRAG istruzione vengono eseguite su un indice alla volta.

DBCC INDEXDEFRAG compatta anche le pagine di un indice, prendendo in considerazione il fattore di riempimento specificato al momento della creazione dell'indice. Le pagine vuote create in seguito alla compattazione vengono rimosse. Per altre informazioni, vedere Specificare un fattore di riempimento per un indice.

Se un indice si estende su più file, DBCC INDEXDEFRAG deframmenta un file alla volta. Le pagine non vengono migrate tra file.

DBCC INDEXDEFRAG indica la percentuale stimata completata ogni cinque minuti. DBCC INDEXDEFRAG può essere arrestato in qualsiasi momento del processo e qualsiasi lavoro completato viene conservato.

A differenza di DBCC DBREINDEX, o l'operazione di compilazione dell'indice in genere, DBCC INDEXDEFRAG è un'operazione online. Non mantiene blocchi a lungo termine. Pertanto, DBCC INDEXDEFRAG non blocca l'esecuzione di query o aggiornamenti. La deframmentazione di un indice relativamente non frammentato risulta più rapida rispetto alla creazione di un nuovo indice. I tempi di deframmentazione infatti sono correlati al livello di frammentazione. Un indice fortemente frammentato potrebbe richiedere molto più tempo rispetto alla ricompilazione.

La deframmentazione viene sempre registrata indipendentemente dal modello di recupero del database impostato. Per altre informazioni, vedere ALTER DATABASE (Transact-SQL). La deframmentazione di un indice fortemente frammentato può generare più log rispetto a una creazione dell'indice completamente registrata. Dato tuttavia che la deframmentazione viene eseguita come una serie di transazioni brevi, se si eseguono backup del log frequenti o si imposta il modello di recupero su SIMPLE, non è necessario un log molto esteso.

Restrizioni

DBCC INDEXDEFRAG consente di ricompilare le pagine foglia dell'indice sul posto. Pertanto, se un indice viene interleavedato con altri indici su disco, l'esecuzione DBCC INDEXDEFRAG su tale indice non rende contigue tutte le pagine foglia nell'indice. Per migliorare il raggruppamento delle pagine, è necessario ricompilare l'indice.

DBCC INDEXDEFRAG non può essere usato per deframmentare gli indici seguenti:

  • Un indice disabilitato.
  • Un indice con blocco di pagina impostato su OFF.
  • Un indice spaziale.

DBCC INDEXDEFRAG non è supportato per l'uso nelle tabelle di sistema.

Set di risultati

DBCC INDEXDEFRAG restituisce il set di risultati seguente (i valori possono variare) se viene specificato un indice nell'istruzione (a meno che non WITH NO_INFOMSGS venga specificato):

Pages Scanned Pages Moved Pages Removed
------------- ----------- -------------
359           346         8
  
(1 row(s) affected)
  
DBCC execution completed. If DBCC printed error messages, contact your system administrator.

Autorizzazioni

Il chiamante deve essere proprietario della tabella o membro del ruolo predefinito del server sysadmin o dei ruoli predefiniti del database db_owner e db_ddladmin.

Esempi

R. Usare DBCC INDEXDEFRAG per deframmentare un indice

Nell'esempio seguente vengono deframmentate tutte le partizioni dell'indice PK_Product_ProductID nella tabella Production.Product del database AdventureWorks2022.

DBCC INDEXDEFRAG (AdventureWorks2022, 'Production.Product', PK_Product_ProductID);
GO

B. Usare DBCC SHOWCONTIG e DBCC INDEXDEFRAG per deframmentare gli indici in un database

Nell'esempio seguente viene illustrato un metodo semplice per deframmentare tutti gli indici di un database il cui livello di frammentazione è superiore alla soglia massima specificata.

/*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

Vedi anche