Syndication : Atom 1.0  RSS 2.0
Blogs des développeurs   »   Le blog d'ElSuket

Article complet: Recherche d'indexes manquants sous SQL Server 2005

08/09/2008

Permalink 23:15:34, Catégories: Indexation, SQL Server, 2342 mots   French (FR) , elsuket

[SGBD][SQL Server] Recherche d'indexes manquants sous SQL Server 2005

Une nouvelle fonctionnalité intéressante, introduite avec SQL Server 2005, est la recherche d’indexes manquants.
Elle permet, de façon très simple, de trouver les indexes manquants qui pourraient simplifier le travail
du moteur de base de données s’ils étaient posés sur des tables de base ou des vues indexées.
Néanmoins, cette fonctionnalité comporte quelques limitations, qui doivent être prise en compte avant qu’on
ait décidé de créer l’index conseillé par SQL Server.
Comme vous le verrez, plusieurs sujets sont connexes à cet article, mais nous ne les aborderons pas ici.
Ils seront l’objet de prochains articles.

[Suite:]

	1. Présentation

Le moteur de base de données comprend, en outre, un optimiseur de requêtes : c’est un des modules pilier d'un SGBD.
Celui-ci est chargé de trouver le meilleur moyen d’exécuter une requête en un minimum de temps et en consommant un minimum de ressources.
Il génère pour cela, à l’enregistrement d’une nouvelle procédure stockée par exemple, un plan de requête qu’il conserve dans
le cache de procédures. Ce plan de requête est généré en fonction des statistiques de colonnes.
Au fur et à mesure que la base de données vit, que les requêtes évoluent, il est possible que les indexes posés il y a quelques temps ne soient plus optimaux.
Dans un tel cas, le moteur de base de données génère un « mauvais » plan de requête.
Cette nouvelle fonctionnalité introduite par SQL Server permet de conserver ces « mauvaises » informations pour nous
faciliter la complexe tâche du paramétrage de base de données.
Il nous reste donc à décider de les implémenter ou non.

	2. Vues de gestion dynamiques impliquées dans la recherche d’indexes manquants

SQL Server 2005 met à notre disposition quatre vues de gestion dynamique.
Nous utiliserons trois de ces vues pour nous aider à la recherche d’indexes manquants :


	- sys.dm_db_missing_index_group_stats:

	Cette vue nous renseignera sur le gain de performances que l’on pourrait obtenir si nous implémentions l’index conseillé.
	Les colonnes qui nous intéressent sont :

		• user_seeks : Nombre de recherches pour lesquelles des requêtes auraient pu tirer profit de l’index 	recommandé.

		• user_scans : Nombre d’analyses d’index pour lesquelles des requêtes auraient pu tirer profit de l’index recommandé.

		• unique_compiles : Nombre de (re)compilations qui auraient pu tirer profit de l’index recommandé. Une recompilation est très coûteuse.

		• avg_total_user_cost : C’est ce que coûte, en moyenne, au moteur de base de données, d’exécuter une requête sans l’index recommandé.

		• avg_user_impact : C’est le gain, en pourcentage, que le moteur de base de données estime pouvoir gagner sur le coût de la requête
		(avg_total_user_cost).

		• last_user_seek : de type DATETIME, elle renseigne sur la date de la dernière occurrence de recherche qui aurait pu profiter
		de l’index conseillé.

		• last_user_scan : même commentaire que pour last_user_seek, excepté qu’il s’agit de la dernière recherche.

	- sys.dm_db_missing_index_groups: 

	Cette vue nous servira à faire le lien entre la vue précédente, qui nous renseigne sur les gains de performance possibles,
	et la vue suivante, qui va nous permettre de créer la commande CREATE INDEX …

	- sys.dm_db_missing_index_details: 

	Cette vue nous éclairera sur les colonnes des tables à indexer. Les colonnes qui nous intéressent sont :

		• equality_columns : liste des colonnes qui constituent un prédicat d’égalité
		 dans l’expression de la requête (WHERE maColonne = maValeur, JOIN maTableB ON maTableA.IDA = maTableB.IDB).

		• inequality_columns : liste des colonnes qui constituent un prédicat d’inégalité
		 (WHERE maColonne < maValeur, JOIN maTableB ON maTableA.IDA > maTableB.IDB).

		• included_columns : liste de colonnes qui permettront de couvrir la requête.

		• statement : nom qualifié de la table sur laquelle l’index doit être posé.

La quatrième vue de gestion dynamique est sys.dm_db_missing_index_columns.
Elle permet d’associer les colonnes de l’index conseillé par sys.dm_db_missing_index_groups et de montrer « en colonne » dans quelle clause de la commande de création des indexes la colonne en question doit se trouver.
C’est ce que propose sys.dm_db_missing_index_details par une liste de colonnes de table, séparées par des virgules.

	3. Une première approche

Relions donc toutes ces informations avec les jointures appropriées :

 
------------------------------ 
- Nicolas SOUQUET - 08/09/2008 
------------------------------ 
 
  SELECT MIGS.unique_compiles Comp, 
      MIGS.user_seeks, 
      MIGS.user_scans, 
      MIGS.avg_total_user_cost, 
      MIGS.avg_user_impact, 
      MIGS.last_user_seek, 
      MIGS.last_user_scan, 
      REPLACE(REPLACE(MID.Statement, '[', ''), ']', '') 'Database.Schema.Table', 
      REPLACE(REPLACE(MID.equality_columns, '[', ''), ']', '') Egalite, 
      REPLACE(REPLACE(MID.inequality_columns, '[', ''), ']', '') Inegalite, 
      REPLACE(REPLACE(MID.included_columns, '[', ''), ']', '') Incluse 
  FROM sys.dm_db_missing_index_group_stats MIGS 
  JOIN sys.dm_db_missing_index_groups MIG ON MIGS.GROUP_HANDLE = MIG.index_group_handle 
  JOIN sys.dm_db_missing_index_details MID ON MIG.INDEX_HANDLE = MID.index_handle 
  WHERE DB_NAME(MID.database_id) NOT IN ('master', 'msdb', 'model', 'ReportServer', 'ReportServerTempDB', 'Distribution', 'TempDB')

Nous avons maintenant toutes les informations pour créer les indexes qui manquent à notre base de données. Mais dans cette foule d’informations, lesquels sont vraiment nécessaires ?
J’ai le souvenir que cette requête m’ait parfois retourné plus de 300 lignes …
Pour trouver dans un premier temps les indexes les plus nécessaires à une base de données pauvrement indexée, il faudrait associer le coût de chaque requête au nombre de recherches et d’analyses d’indexes,
et de (re)compilations de plans de requête, et tenir compte de la « fraîcheur » des données retournées par ces vues de gestion dynamique.

Soit donc la requête suivante :

 
------------------------------ 
- Nicolas SOUQUET - 08/09/2008 
------------------------------ 
 
  SELECT ROUND((MIGS.user_seeks + MIGS.user_scans + MIGS.unique_compiles) * MIGS.avg_total_user_cost * MIGS.avg_user_impact, 0) Avantage, 
      MIGS.last_user_seek, 
      MIGS.last_user_scan, 
      REPLACE(REPLACE(MID.Statement, '[', ''), ']', '') 'Database.Schema.Table', 
      REPLACE(REPLACE(MID.equality_columns, '[', ''), ']', '') Egalite, 
      REPLACE(REPLACE(MID.inequality_columns, '[', ''), ']', '') Inegalite, 
      REPLACE(REPLACE(MID.included_columns, '[', ''), ']', '') Incluse 
  FROM sys.dm_db_missing_index_group_stats MIGS 
  JOIN sys.dm_db_missing_index_groups MIG ON MIGS.GROUP_HANDLE = MIG.index_group_handle 
  JOIN sys.dm_db_missing_index_details MID ON MIG.INDEX_HANDLE = MID.index_handle 
  WHERE CONVERT(CHAR(10), MIGS.LAST_USER_SEEK, 103) = CONVERT(CHAR(10), GETDATE(), 103) 
  AND DB_NAME(MID.database_id) NOT IN ('master', 'msdb', 'model', 'ReportServer', 'ReportServerTempDB', 'Distribution', 'TempDB') 
  ORDER BY Avantage DESC

Maintenant, nous avons les indexes manquants qui ont coûté le plus cher à notre serveur, et qui auraient même été nécessaires aujourd’hui.
Si l’on ré-exécute cette requête quelques secondes après l’avoir exécutée une première fois sur une base de données OLTP,
ou sur un serveur OLAP très utilisé, et que l’on constate que les premières lignes (c'est-à-dire celles qui nous renseignent
sur les indexes les plus nécessaires) ont un «avantage » bien supérieur à celui de la première exécution, c’est très
certainement que si votre serveur était doué de parole, il vous remercierait de l’avoir créé.
Mais alors, comment créer ces indexes ?

	4.Création des indexes nécessaires

Vous aurez certainement dénoté la simplicité avec laquelle SQL Server 2005 nous expose les indexes qu’il serait nécessaire de créer. Prenons la syntaxe de la commande CREATE INDEX, sans ses options :

CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name  
  ON <object> ( column [ ASC | DESC ] [ ,...n ] )  
  [ INCLUDE ( column_name [ ,...n ] ) ]

En supposant que nous avons au moins l’index de clé primaire, cluster, sur les tables montrées par les premières lignes de la requête précédente, nous créerons simplement notre commande en remplaçant :

- column par les colonnes de table listées dans les colonnes Egalite et Inegalite de la précédente requête,
- column_name dans la clause INCLUDE par les colonnes de table listées dans la colonne Incluse de la précédente requête

Il y a une dernière petite subtilité : nous devons placer les colonnes d’égalité avant celles d’inégalité dans la clause ON, mais également veiller à ordonner les colonnes d’égalité dans l’ordre décroissant de leur sélectivité.

En effet, l’optimiseur de requête de SQL Server 2005 (et d’autres SGBD) est basé sur les coûts, c'est-à-dire la quantité de ressources qui vont être nécessaires à l’exécution d’une requête.
Il se base sur la sélectivité des colonnes, c'est-à-dire le nombre de valeurs différentes que contiennent chacune des colonnes de nos tables, pour estimer ce coût.
Ces statistiques sont conservées soit au niveau colonne (node « Statistiques » des tables dans SQL Server Management Studio), soit dans les indexes.
Par opposition à une colonne de type BIT qui est très peu sélective, une colonne auto-incrémentée est très sélective.

Pour rechercher les données qui sont la réponse à notre requête, l’optimiseur de requêtes va commencer par rechercher nos
critères (clause WHERE de la commande SELECT, par exemple) dans les colonnes ayant la sélectivité la plus élevée, de sorte
qu’il aura ensuite un jeu de données le plus petit possible pour vérifier les autres contraintes de la requête.
Nous veillerons donc à vérifier l’ordre dans lequel nous allons ordonner nos colonnes d’ « égalité » : les vues de gestion dynamique les retournent souvent dans le bon ordre, mais une requête :

SELECT COUNT(DISTINCT maColonne) FROM maTable

nous ôtera les doutes.

Comme le moteur de bases de données ne peut pas maintenir des statistiques sur des données qui ne sont pas
contenues dans les colonnes, il découle que les colonnes d’inégalité révélées par notre dernière requête devront se
trouver à la suite des colonnes répertoriées comme colonnes d’ « égalité ».

Qu’en est-il des colonnes répertoriées « Incluse » ? Ces colonnes, qui sont répertoriées dans le SELECT de nos requêtes,
à l’exception des colonnes participant à un calcul agrégé (SUM, MIN, MAX, …) permettent de couvrir nos requêtes en évitant
les bookmarks lookups, eux-aussi très coûteux.
Les colonnes incluses sont également une nouvelle fonctionnalité introduite avec SQL Server 2005.

Finalement, la trame de notre requête d’index sera :

CREATE INDEX IX_maTable_mesColonnes 
ON monSchema.maTable (mesColonnesEgalite, mesColonnesInegalite) 
INCLUDE (mesColonnesIncluse) 
WITH (mesOptions)

	5.Limitations de la fonctionnalité d’indexes manquants

Cette fonctionnalité a cependant quelques revers : 

	- Comme nous l’avons vu, elle retourne une liste de colonnes mais ne précise pas dans quel ordre elles doivent constituer la clé de l’index,

	- Elle ne constitue pas une aide à la configuration d’un index (options FILLFACTOR et PAD_INDEX),

	- Dans certains cas, elle ne renseigne que sur les colonnes incluses. Il faudra donc chercher quelle(s) est la
	 requête à l’origine  de ce groupe d’index manquant, puis optimiser la requête en conséquence

	- Elle ne renseigne pas sur la « fraîcheur » des données : la requête que je vous propose peut tout à fait montrer un
	 « avantage » énorme, qui a été généré par une requête que nous avons modifiée il y a quelques jours. 

	En effet, ces informations sont purgées :
		• Lors du redémarrage du serveur ou du service SQL Server,
		• Lors de la création d’un index sur une table pour laquelle la fonctionnalité nous conseille la création de plusieurs indexes.
	6.Conclusion

Comme nous venons de le voir, cette fonctionnalité permet d’indexer très rapidement une base de données qui ne l’est que très pauvrement, mais elle permet aussi de suivre la vie de la base de données.

Même si cette fonctionnalité ne constitue pas un outil précis de paramétrage de base de données (en existe-t-il ?), elle nous aidera à vérifier, en plus des options d’instruction (SET STATISTICS)
et du plan de requête (accessible par CTRL+L sous SQL Server Management Studio) si, lorsque l’on doit optimiser une requête, on doit se tourner vers la création d’un index approprié,
ou bien vers une autre expression de la même requête (parfois ce sera les deux)

ElSuket

Social Bookmarking:

                                     

Commentaires, Pingbacks:

Connectez-vous pour vous abonner à cet article:

Flux de commentaires pour cet article : Atom 1.0  RSS 2.0
Commentaire de: ylarvor [Membre]
Bienvenue dans la communauté des blogs autours de SQL Serveur.

Yann.
Permalien 20/09/2008 @ 16:07
Commentaire de: sqlpro [Membre] · http://sqlpro.developpez.com
je me suis amusé à travers l'artcle qur "quoi indexer" de fabriquer une requête qui "pisse" tous les CREATE INDEX manquants...
A lire : http://sqlpro.developpez.com/cours/quoi-indexer/#LXII
mais à utiliser avec des pincettes !

A +
Permalien 02/10/2008 @ 18:58
Commentaire de: cavo789 [Membre]
Très clair et instructif.
Merci.
Permalien 12/12/2008 @ 15:52

Vous devez être identifié pour poster un commentaire.

Liste des blogs

Le blog d'ElSuket

ElSüket

Rechercher

<  Mai 2012  >
Lun Mar Mer Jeu Ven Sam Dim
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

Liens

Indexation

  • [.NET][SGBD][SQL Server] Différence entre ALTER INDEX ... REBUILD et ALTER INDEX ... REORGANIZE

    Après avoir vu ce que sont la fragmentation interne et externe d'un index, voyons les différences entre les options REBUILD et REORGANIZE de l'instruction ALTER INDEX (ou respectivement DBCC DBREINDEX ou DBCC INDEXDEFRAG sous SQL Server 2000)
    ]suite

    Permalien
  • [SGBD][SQL Server] Différence entre fragmentation interne et externe d'un index

    Quand on parle de la fragmentation physique des indexes, on parle aussi de fragmentation externe. Celle-ci se "produit" lorsque l'ordre logique des pages de l'index est incorrect. Les nouvelles valeurs de clé de l'index sont alors insérées dans de nouvelles pages d'index, qui désordonnent l'ordre original de la clé de l'index.

    Quand on parle de fragmentation logique de l'index, on parle aussi de fragmentation interne : c'est le cas lorsque la quantité de données stockée dans les pages de l'index est plus petite que la quantité maximale de données que peut stocker une page.

    ElSuket

    Permalien
  • [.NET][SGBD][SQL Server] Lister les caractéristiques des indexes sous SQL Server 2005 et 2008

    Voici une requête qui nous permet de retrouver pour tout index :

    - la liste de ses colonnes clé
    - la liste de ses colonnes incluses
    - la définition de son filtre
    - le script de création de cet index

    ]suite

    Permalien
  • [SGBD][SQL Server] Lister les colonnes des index d'une base de données

    Voici une petite requête qui permet de lister les colonnes de tous les index d'une base de données, avec leur type et l'ordre des colonnes dans la clé de l'index :
    ]suite

    Permalien
  • [SGBD][SQL Server] Purge du cache de plans

    Il est possible qu'un jour vous trouviez dans les journaux de SQL Server le libellé suivant :

    SQL Server has encountered n occurrence(s) of cachestore flush for the (partie du cache de plans) cachestore due to some database maintenance or reconfigure operations"

    Ce message n'apparaît qu'à partir du SP2 de SQL Server 2005, et il est écrit par intervalles de 5 minutes.
    La purge du cache de plans peut se produire dans les cas suivants :
    ]suite

    Permalien
  • [SGBD][SQL Server] Recherche d'indexes manquants sous SQL Server 2005

    Une nouvelle fonctionnalité intéressante, introduite avec SQL Server 2005, est la recherche d’indexes manquants.
    Elle permet, de façon très simple, de trouver les indexes manquants qui pourraient simplifier le travail
    du moteur de base de données s’ils étaient posés sur des tables de base ou des vues indexées.
    Néanmoins, cette fonctionnalité comporte quelques limitations, qui doivent être prise en compte avant qu’on
    ait décidé de créer l’index conseillé par SQL Server.
    Comme vous le verrez, plusieurs sujets sont connexes à cet article, mais nous ne les aborderons pas ici.
    Ils seront l’objet de prochains articles.

    ]suite

    Permalien
  • [.NET][SGBD][SQL Server] Rechercher les index inutiles

    Si les index représentent l'optimisation la plus simple à mettre en place, on souhaite néanmoins conserver le minimum d'entre-eux, car leur maintenance lors de l'exécution de requêtes de modifications de données (INSERT, UPDATE, DELETE) peut être coûteuse, surtout sur des tables volumineuses.
    Voyons comment collecter cette information ...
    ]suite

    Permalien
  • [.NET][SGBD][SQL Server] Une procédure pour connaître l'état physique et l'utilisation des index

    Voici une petite procédure stockée qui permet de connaître l'état physique des index (nombre de pages du niveau feuille, fragmentation et taux d'utilisation des pages) en même temps que la façon dont ils sont utilisés (nombres de seeks et de scans, ...).

    Elle est utilisable pour collecter ces statistiques sur l'ensemble d'une base de données, ou bien sur une table en particulier
    ]suite

    Permalien
  • [SGBD][SQL Server] Une procédure stockée pour défragmenter les indexes sous SQL Server 2005 et ultérieur

    Voici une petite procédure stockée que l'on peut exécuter régulièrement dans un job pour défragmenter les indexes de toutes les bases de données, en fixant les seuils de nombre de page et de pourcentage moyen de fragmentation

    ]suite

    Permalien
  • [SGBD][SQL Server] [Agent SQL Server] Gestion de l'historique

    Outre sa principale fonctionnalité de gestion d'exécutions, l'Agent SQL Server comporte quelques fonctionnalités intéressantes concernant la gestion de son historique.
    ]suite

    Permalien

Snippets

  • [SGBD][SQL Server] Calculer le Buffer Cache Hit Ratio

    S'il est une valeur intéressante à suivre pour le performances d'un serveur, c'est bien le Buffer Cache Hit Ratio, ou Taux d'accès au cache des tampons, car celui-ci est un rapport du nombre de pages lues en RAM par rapport au nombre de pages lues à partir des disques.

    Voici une petite requête pour trouver sa valeur :

    ]suite

    Permalien
  • [SGBD][SQL Server] Caractériser une adresse IP

    Voici une procédure stockée pour :

    - vérifier une adresse IP
    - chercher si celle-ci est privée
    - chercher la classe de cette adresse IP

    ]suite

    Permalien
  • [SGBD][SQL Server] Comment exécuter une procédure stockée dès le démarrage de SQL Server ?

    Nous allons voir comment on peut exécuter n'importe quelle procédure stockée dès le démarrage de SQL Server, à l'aide de la procédure stockée sp_procoption

    ]suite

    Permalien
  • [SGBD][SQL Server] Concaténer les valeurs d'une colonne dans une variable

    Il est souvent demandé s'il est possible de concaténer les valeurs d'une colonne dans une variable, éventuellement en les séparant avec un symbole de ponctuation.
    Voici comment faire, sans curseur ni expression de table commune ...
    ]suite

    Permalien
  • [SGBD][SQL Server] Connaître l'état d'un service : xp_servicecontrol

    Comment connaître simplement l'état d'un service ?
    Est-il possible d'arrêter et de démarrer un service avec une requête ?

    ]suite

    Permalien
  • [SGBD][SQL Server] Consulter l'historique des restaurations de bases de données

    Voici une petite requête qui permet de voir toutes les restaurations de bases de données d'une instance ...

    ]suite

    Permalien
  • [SGBD][SQL Server] Créer une table de dates

    Pourquoi ne pas créer une table de dates pour se faciliter les recherches dans des tables suivant la colonne de type date qu'elles contiennent ?
    On peut vous demander par exemple de rechercher la quantité d'eau consommée par un parc de machines pour la deuxième semaine de chaque mois d'une année.
    Imaginez un peu la complexité de la requête à écrire ...
    Voyons comment on peut résoudre cette demande très facilement en créant une table de dates ...

    ]suite

    Permalien
  • [SGBD][SQL Server] Découper une chaîne en sous-chaînes de longueur fixe

    Certains me désignent sur le forum SQL Server comme l'homme qui murmure à l'oreille des CTE.
    En voici donc une nouvelle !

    ]suite

    Permalien
  • [SGBD][SQL Server] Détecter un caractère unicode dans une chaîne de caractères

    Voici une petite fonction qui permet de vérifier la présence d'un caractère qui n'est pas supporté par la norme ASCII dans une chaîne de caractères ...

    ]suite

    Permalien
  • [SGBD][SQL Server] Exemples d'affectations de variables en ligne sous SQL Server 2008

    Voici quelques exemples simples de code qui montrent que sous SQL Server 2008, on peut non seulement se passer des sempiternelles deux lignes de code nécessaires jusqu'en version 2005 pour déclarer et affecter d'un valeur une variable, mais on peut aller encore plus loin ...

    ]suite

    Permalien

Syndiquez ce blog XML

Articles :

Commentaires :

 
 
 
 
Partenaires

Hébergement Web