DBCC INDEXDEFRAG (Transact-SQL)

S’applique à :SQL ServerAzure SQL Managed Instance

Défragmente les index de la table ou de la vue spécifiée.

Important

Cette fonctionnalité sera supprimée dans une prochaine version de Microsoft SQL Server. Évitez d'utiliser cette fonctionnalité dans de nouveaux travaux de développement, et prévoyez de modifier les applications qui utilisent actuellement cette fonctionnalité. Utilisez ALTER INDEX à la place.

S’applique à : SQL Server 2008 (10.0.x) et versions ultérieures

Conventions de la syntaxe Transact-SQL

Syntaxe

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 ]

Notes

Pour afficher la syntaxe Transact-SQL pour SQL Server 2014 et versions antérieures, consultez Versions antérieures de la documentation.

Arguments

database_name | database_id | 0

Base de données contenant l'index à défragmenter. Si 0 est spécifié, la base de données active est utilisée. Les noms de base de données doivent suivre les règles applicables aux identificateurs.

table_name | table_id | view_name | view_id

Table ou vue contenant l'index à défragmenter. Les noms des tables et des vues doivent suivre les règles applicables aux identificateurs.

index_name | index_id

Nom ou ID de l'index à défragmenter. Si aucun ID n'est spécifié, l'instruction défragmente tous les index pour la table ou la vue indiquées. Les noms d'index doivent respecter les règles applicables aux identificateurs.

partition_number | 0

Numéro de la partition de l'index à défragmenter. S'il n'est pas spécifié ou si la valeur 0 est spécifié, l'instruction défragmente toutes les partitions dans l'index indiqué.

WITH NO_INFOMSGS

Supprime tous les messages d'information dont les niveaux de gravité sont compris entre 0 et 10.

Notes

DBCC INDEXDEFRAG défragmente un index au niveau feuille afin que l'ordre physique des pages corresponde à l'ordre logique (de gauche à droite) des nœuds feuilles, améliorant ainsi les performances d'analyse de l'index.

Notes

Quand DBCC INDEXDEFRAG est exécuté, la défragmentation de l'index se produit de manière séquentielle. Cela signifie que l'opération est effectuée sur un seul index à l'aide d'un thread unique. Il n'y a aucun parallélisme. En outre, les opérations sur plusieurs index sont effectuées à partir de la même instruction DBCC INDEXDEFRAG, sur un index à la fois.

DBCC INDEXDEFRAG compacte également les pages d'un index, en tenant compte du facteur de remplissage spécifié lors de la création de l'index. Toute page vide issue de ce compactage est supprimée. Pour plus d’informations, consultez Spécifier un facteur de remplissage pour un index.

Si un index s'étend sur plusieurs fichiers, DBCC INDEXDEFRAG défragmente un fichier à la fois. Les pages ne migrent pas d'un fichier à l'autre.

Toutes les cinq minutes, DBCC INDEXDEFRAG affiche une estimation du pourcentage d'achèvement. DBCC INDEXDEFRAG peut être arrêté à n'importe quel stade du processus, chaque travail terminé étant conservé.

À l'inverse de DBCC DBREINDEX ou de la génération d'index en règle générale, DBCC INDEXDEFRAG est une opération en ligne. Les verrous ne sont pas conservés à long terme. DBCC INDEXDEFRAG ne bloque donc pas les requêtes ou mises à jour en cours d'exécution. Un index relativement non fragmenté peut être défragmenté plus rapidement que la construction d'un nouvel index, car le temps de défragmentation dépend du volume de fragmentation. Un index fortement fragmenté peut être beaucoup plus long à défragmenter qu'à regénérer.

La défragmentation est toujours complètement enregistrée, quel que soit le paramètre du mode de récupération de la base de données. Pour plus d’informations, consultez ALTER DATABASE (Transact-SQL). La défragmentation d'un index fortement fragmenté peut générer un journal plus volumineux que la création d'un index avec journalisation complète. Toutefois, la défragmentation s'effectue sous la forme d'une série de transactions courtes et ne requiert donc pas un journal volumineux si des sauvegardes de fichier journal sont effectuées fréquemment ou que le paramètre du mode de récupération est SIMPLE.

Restrictions

DBCC INDEXDEFRAG mélange les pages feuilles de l'index en place. Ainsi, si un index est entrelacé avec d'autres sur le disque, l'exécution de DBCC INDEXDEFRAG sur cet index ne rend pas toutes ses pages feuilles contiguës. Pour améliorer le clustering des pages, régénérez l'index.

DBCC INDEXDEFRAG ne peut pas être utilisé pour défragmenter les index suivants :

  • un index désactivé ;
  • un index dont le verrouillage de page est désactivé (OFF) ;
  • un index spatial.

DBCC INDEXDEFRAG ne peut pas être utilisé sur des tables système.

Jeux de résultats

DBCC INDEXDEFRAG retourne le jeu de résultats suivant (les valeurs peuvent varier) si un index est spécifié dans l’instruction (sauf si WITH NO_INFOMSGS est défini) :

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.

Autorisations

L’appelant doit être propriétaire de la table ou être membre du rôle serveur fixe sysadmin, du rôle de base de données fixe db_owner ou du rôle de base de données fixe db_ddladmin.

Exemples

R. Utiliser DBCC INDEXDEFRAG pour défragmenter un index

L’exemple suivant défragmente toutes les partitions de l’index PK_Product_ProductID dans la table Production.Product de la base de données AdventureWorks2022.

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

B. Utiliser DBCC SHOWCONTIG et DBCC INDEXDEFRAG pour défragmenter les index d'une base de données

L'exemple suivant illustre une méthode simple de défragmentation de tous les index d'une base de données fragmentés au-delà d'un seuil déclaré.

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

Voir aussi