dimanche 23 juin 2013

Statistiques ORACLE, Package DBMS_STAT

La semaine dernière, et lors d’une mission de consulting chez un opérateur télécoms, on a confronté un problème de performance qui concerne les statistiques.

Bref, le problème est le suivant :

L’équipe de développement a  développé une application qui utilise une base de données Oracle 10g. Au niveau du serveur de recette l’application marche très bien, avec un temps de réponse raisonnable pour  la plus part des requêtes, mais une fois l’application est en production, oooops le temps de réponse est vraiment anormale (Exemple : une requête en recette : 15s, en prod : 3 minutes !!!!!!!!!!!!!).

NB : Avant mon intervention, ils ont bien vérifié que la configuration des 2 serveurs (Recette et Prod) ont les mêmes caractéristiques . Les 2 BD ont aussi la même volumétrie.

Avant de commencer d’inspecter les plans d’exécutions, il fallait voir les statistiques utilisées par Oracle. On sait parfaitement qu’Oracle se base sur les statistiques collectées pour déterminer le meilleur plan d’exécution. Si on arrive à avoir les mêmes statistiques que le serveur de recette, il nous suffit de rejouer son scénario et si le problème vient réellement d'un plan d'exécution différent, alors on va  pouvoir identifier la ou les requêtes en question.


Pour cela, on va sauvegarder les statistiques du serveur de recette :


1-      Créer une table pour sauvegarder les statistique : (USER à le schéma qui utilise l ’application, NOM_TABLE_STATS à Nom de la table des statistiques)

     exec DBMS_STATS.CREATE_STAT_TABLE (ownname=>'USER', stattab=>'NOM_TABLE_STATS');

2-      Alimenter la table NOM_TABLE_STATS par les statistiques du serveur de recette (A travers un Export du package DBMS_STATS)

    exec DBMS_STATS.EXPORT_SCHEMA('USER','NOM_TABLE_STATS');

3-      Au niveau du serveur PROD, importer les statistique déjà collectées :
-          Pour cela, il faut déjà supprimé les statistiques du PROD par la commande suivante :
exec DBMS_STATS.DELETE_SCHEMA_STATS('USER',FORCE=>TRUE);

-          Importer les statistiques :
 exec DBMS_STATS.IMPORT_SCHEMA_STATS('USER','NOM_TABLE_STATS');

Et voilà, maintenant on a les même statistiques au niveau des 2 serveurs, après les tests au niveau de la PROD, on a constaté que le temps de réponse est très raisonnable.

NB : Normalement c’est la première étape qu’on doit faire, il y a des cas où le problème persiste toujours, dans ce cas il faut revoir et analyser les plans d’exécutions pour voire s’il y a des full scan ou des mauvaises utilisation d’index ou bien autre chose.


Zakaria EL HAMDAOUI
Consultant Oracle