Articles Tagués ‘Index’

Visualiser les histogrammes des statistiques des index

12 juin 2011

En auditant les statistiques d’une base de de données chez un client, j’ai eu l’idée de créer un rapport qui afficherait de façon plus lisible les STATISTICS des tables.

J’aurai aimé vous faire un cours complet sur les statistiques dans SQL Server mais on va raccourcir un peu.
Quand vous regardez le détail d’une statistique d’une table dans Management Studio, vous obtenez un joli tableau en ASCII-art (cf. ci-dessous).

image

Evidemment, vous savez tous que vous avez toutes les données avec l’instruction DBCC SHOW_STATISTICS(table, index).
Néanmoins, ce n’est pas forcément plus lisible pour autant.

J’ai donc fait un rapport Reporting Services qui appelle les différentes variante de DBCC SHOW_STATISTICS :

DBCC SHOW_STATISTICS(DimCustomer, IX_GeoKey) WITH HISTOGRAM
DBCC SHOW_STATISTICS(DimCustomer, IX_GeoKey) WITH STAT_HEADER
DBCC SHOW_STATISTICS(DimCustomer, IX_GeoKey) WITH DENSITY_VECTOR

Le plus utile est la représentation des histogrammes qui nous renseigne sur la répartition des enregistrements sur les valeurs de la clé.

image

Evidemment, j’en ai profité pour rendre plus lisible les densités (la notation scientifique avec des 10-6 ne me parle pas nativement) et les informations diverses.

Enfin, j’ai créé le rapport avec comme paramètre le nom de la base de données. Le rapport génère les infos pour tous les index.

Dès que j’ai un peu de temps, je traduis tout en anglais et je le pousse sur CodePlex (il n’y a que 2 fichiers RDL mais bon, c’est déjà ça).

 

Tip bonus du jour : si votre base de données utilise des Schemas, pensez à encadrer le nom de la table par des QUOTED_IDENTIFIER (“” ou []) dans l’instruction DBCC SHOW_STATISTICS.

SQL Internals Viewer et SQL 2008 R2

25 avril 2011

Il existe un outil très intéressant sur CodePlex pour analyser visuellement la fragmentation interne de vos fichiers MDF et NDF.

Internals Viewer for SQL Server

image

Cet outil gratuit se présente sous la forme d’un addin à Management Studio (SSMS). Il détaille toutes les pages par index.

Sauf qu’entre SQL Server 2008 et 2008 R2, il y a eu des modifications dans les API entrainant une incompatibilité (breaking change en anglais). Si vous le téléchargez, vous aurez une erreur au démarrage (No such interface supported).

Pour le faire fonctionner (sans revenir à la version précédente de Management Studio), je vous invite à télécharger le code et supprimer ces quelques lignes :

 

/*
 * Legacy Code (SQL 2005 et 2008) 
 */
//IObjectExplorerEventProvider provider = ServiceCache.GetObjectExplorer().GetService(typeof(IObjectExplorerEventProvider)) as IObjectExplorerEventProvider; 
//provider.NodesRefreshed += new NodesChangedEventHandler(Provider_NodesRefreshed); 
//provider.NodesAdded += new NodesChangedEventHandler(Provider_NodesRefreshed); 
//provider.BufferedNodesAdded += new NodesChangedEventHandler(Provider_NodesRefreshed); 

 

Il vous faudra également mettre à jour quelques références (SmoEnum qui n’existe plus par exemple ou bien le chemin vers les assemblies si vous êtes en x64). Redéployez et le tour est joué.

Evidemment, ce n’est pas la solution la plus académique mais c’est pragmatique en attendant un vrai support des Addins dans SSMS.

 

Merci à Jonathan Kehayias (SQL 2008 R2 Breaks SSMS Addins) même si ça n’a pas tout résolu Sourire.

Merci à mes partenaires de tarot qui ont supporté ma séance de débogage pendant nos parties.

Update, Lock et Table

27 février 2011

Le débat de fin de semaine à Bewise est organisé par Sébastien. Ca parle de Lock, d’index et d’update sur une table.

Comme il en parle mieux que moi, je vous renvoie sur son blog où tout est détaillé : http://www.dotmim.com/2011/02/25/un-update-locke-til-toute-une-table/

Merci pour cet éclaircissement Monsieur Mim.

Fragmentation et plan de maintenance

28 mars 2010

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 : http://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écialiste.


Suivre

Recevez les nouvelles publications par mail.

Joignez-vous à 325 followers