Fragmentation et plan de maintenance

Malheureusement, tout le monde ne le sait pas toujours mais une base de données se fragmente avec le temps. Je vous renvoie à un précédent post : https://blog.djeepy1.net/2008/08/13/indexation-gerer-la-fragmentation/ pour les détails.

Le billet du jour est lié aux plans de maintenance “automatique”. En effet, je vois souvent des SI dans lesquels l’administrateur ou l’équipe de développement sont fiers de m’annoncer qu’ils ont mis des plans de maintenance en place pour gérer la fragmentation.

C’est bien sauf que, si la base est conséquente, ces maintenances automatiques peuvent faire plus de tort que de bien.

En effet, le composant Rebuild Index Task, dans sa configuration par défaut reconstruit TOUS les index de TOUTES les tables.

image

Le problème est que si vous avez des tables importantes (plusieurs millions de lignes et plusieurs Go de données), reconstruire l’index CLUSTERED peut être une opération lourde :

  • Remplissage du LOG (si vous êtes en RECOVERY FULL)
  • Lock de la table (si vous êtes en Standard Edition)
  • Opération longue

D’autant plus que la tâche génère un script SQL par ordre alphabetique des index et non dans un ordre logique. On reconstruirait normalement les CLUSTERED puis les NON-CLUSTERED.

Bref, j’ai été confronté à des situations où cette tâche engendrait plus de problèmes qu’elle n’en résolvait. Par exemple, la tâche qui dure jusqu’au petit matin, se superposant à un autre plan de maintenance (le backup), dégradant les performances d’un job de synchro, etc.

La solution

La solution consiste à faire un job un peu plus complexe. L’idée est de se baser sur la vue système nous donnant les infos de fragmentation : sys.dm_db_index_physical_stats. Déjà, on peut filtrer sur les index les plus fragmentés (> 25/30% pour moi).

On croise ensuite avec les infos de l’index (type CLUSTERED ou non) et les infos de volumétrie (nombre de lignes) que l’on trouve respectivement dans sys.indexes et sys.partitions.

A partir de ces informations, je peux donc obtenir dynamiquement les instructions à jouer.

SELECT 
    Schema_Name(o.schema_id) as SchemaName,
    OBJECT_NAME(stat.object_id) as TableName,
    ix.name, stat.index_id, 
    avg_fragmentation_in_percent, ix.fill_factor, rows,
    'Alter Index ['+ ix.name
        + '] on [' + Schema_Name(o.schema_id) 
        + '].[' + OBJECT_NAME(stat.object_id) 
        + '] Rebuild' as Statement
FROM sys.dm_db_index_physical_stats(
    DB_ID('AdventureWorks'),
    NULL,
    NULL, NULL, NULL) stat
  inner join sys.indexes ix 
    on ix.index_id = stat.index_id
    and ix.object_id = stat.object_id
  inner join sys.partitions p
    on ix.index_id = p.index_id
    and ix.object_id = p.object_id
  inner join sys.objects o on stat.object_id = o.object_id
where avg_fragmentation_in_percent > 25
order by index_id, avg_fragmentation_in_percent desc

 

Je prends toutefois ces informations avec précaution. En effet, j’essaie d’avoir une idée de la durée de chaque reconstruction en fonction de la volumétrie. Ceci pour faire ma planification au mieux. Par exemple si en testant (eh oui, le test reste primordial) je m’aperçois que la reconstruction de tel index prends 35 minutes, je l’isole et le planifie à part, à un moment où cela ne va pas gêner les autres tâches.

Pour cela, il suffit de bien connaître sa base et ce qui s’y passe.

 

Epilogue

Malgré toute la pédagogie que nous pouvons faire lors de formation, consulting, projets, etc., les développeurs ne sont pas encore assez vigilants aux problématiques de base de données et pensent qu’un produit comme SQL Server se maintient tout seul à un haut niveau de performance. Je prends souvent la métophore avec l’automobile. Cela fait quelques siècles que ça existe et pourtant vous allez toujours au garage régulièrement ;-).

Evidemment, loin de moi l’idée d’entretenir le clivage DBA/développeurs. Mon métier de consultant me place bien souvent au milieu et je privilégie la pédagogie.

Donc la règle à retenir : SQL Server est un produit puissant mais complexe, faites-vous aider par des spécialistes.

2 réflexions sur “Fragmentation et plan de maintenance

  1. Heu, par hasard, n’oublierais tu pas un point essentiel : avant de réindexer, teste les stats de ton index pour savoir s’il est utilisé … Un algo + puissant prenant en compte la taille de l’index et ses stats d’usage (dm_db_index_usage_stats) est préférable, à mon sens.

    • Oui, en effet, c’est une vérification supplémentaire. Mais en règle générale, je fais la chasse aux index inutiles (inutilisés) en parallèle des plans de maintenance. Pour moi, un idex est utilisé ou il n’existe pas.

Votre commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Image Twitter

Vous commentez à l’aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s