Vous êtes sur la page 1sur 59

Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 

Chapitre 12 : Gestion des tables et des index


• Vue d'ensemble
• Gestion des tables
• Gestion des index B-tree
• Les statistiques et l'optimiseur Oracle
• Utiliser le Database Control

Vue d’ensemble
Parmi les principaux types d’objets d’un schéma, seuls les tables et les index occupent de
l’espace de stockage en dehors de leur définition dans le dictionnaire.

Cet espace de stockage doit être planifié correctement pour éviter les erreurs liées au
manque d’espace ou les problèmes de performance.

Les tables et les index sont des segments ; le stockage est donc organisé en extensions,
piloté par la clause STORAGE et par les caractéristiques du tablespace. Par ailleurs,
l’organisation du stockage dans les blocs a de l’importance.

Il existe d’autres types d’objets qui occupent de l’espace de stockage, mais ces derniers
sortent du périmètre de cet ouvrage :

• Vues matérialisées : structure analogue à une table et dont le contenu est


périodiquement mis à jour à partir d’une requête SELECT.
• IOT (Index Organised Table - table organisée en index) : table dont le stockage est
organisé dans l’index de la clé primaire de la table.
• Clusters : structures qui permettent de stocker physiquement ensemble des tables
fréquemment interrogées par jointure.
• Tables et index partitionnées : depuis la version 8, l’option partitionnement permet
de découper le stockage physique des tables et des index en morceaux plus petits
appelés partitions.

De même, il existe plusieurs types d’index :

• Index B-tree : index classique qui sera étudié dans cet ouvrage.
• Index Bitmap : index dont le stockage est organisé différemment des index B-tree et
qui est plutôt destiné à l’indexation des colonnes à faible cardinalité dans un
environnement décisionnel (l’index bitmap est très coûteux en mise à jour).
• Index à clé inversée : index B-tree qui indexe non pas la valeur de la colonne mais
une valeur résultant de l’inversion des octets de la colonne (intéressant pour
l’indexation de colonnes qui sont insérées en ordre croissant et interrogées par
égalité).
• Index basé sur des fonctions : index B-tree qui indexe non pas la valeur de la
colonne mais le résultat de l’application d’une fonction SQL (UPPER, LOWER, etc.) à
la valeur de la colonne. Il est intéressant lorsque la colonne n’est pas interrogée
directement (colonne opérateur valeur) mais avec la fonction (fonction(colonne)
opérateur valeur).

1 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Gestion des tables


1. Organisation du stockage dans les blocs
a. Principes

Structure du bloc

L’en-tête du bloc contient l’adresse du bloc, le type de segment, un répertoire des tables,
un répertoire des lignes et des entrées pour les transactions. La taille de l’en-tête du bloc
est variable, de l’ordre de 100 octets à 200 octets. Le reste du bloc contient les données
(une à plusieurs lignes de la table) et de l’espace libre.

L’en-tête est stocké dans la partie haute du bloc et les données sont insérées à partir du
bas. L’en-tête est susceptible de grossir (vers le bas) en fonction de l’activité dans le
bloc ; il ne rétrécit jamais. Par exemple, si 100 lignes sont insérées dans le bloc, le
répertoire des lignes situé dans l’en-tête grossit ; si les lignes sont ensuite supprimées, le
répertoire des lignes ne rétrécit pas (l’espace est conservé et pourra être réutilisé si des
lignes sont de nouveaux insérées dans le bloc).

Structure d’une ligne

L’en-tête d’une ligne contient quelques informations sur la ligne (nombre de colonnes,
chaînage éventuel, verrou). La taille de l’en-tête de lignes est variable (3 octets
minimum). Ensuite, chaque colonne est stockée avec un en-tête de colonne (qui donne la
longueur de la colonne sur 1 à 3 octets) suivi de la valeur de la colonne.

2 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

La longueur totale d’une ligne dépend du nombre de colonnes et de la valeur stockée dans
chaque colonne, la longueur de la colonne dépendant du type de données.

Exemple :

Type Longueur du stockage


Longueur fixe (n octets), quelle que soit la valeur stockée dans la
CHAR(n)
colonne.
Longueur variable (0 à n octets), dépendant de la valeur stockée
VARCHAR2(n)
dans la colonne.
Longueur variable (entre 1 et 21 octets) dépendant de la valeur
NUMBER(x,y)
stockée dans la colonne.
DATE Longueur fixe (8 octets).
CLOB, BLOB Longueur variable, jusqu’à 2^32 blocs Oracle.

Une valeur NULL occupe un octet en milieu de ligne et aucun en fin de ligne.

Les fonctions SQL VSIZE et DUMP appliquées à une valeur (colonne, résultat d’une
expression) permettent de connaître respectivement la taille en octets du stockage
interne de la valeur et la représentation interne de la valeur.

Ce qu’il faut retenir, c’est que le bloc ne contient pas que des données utiles ; il y a des données
de contrôle, de surcharge, utilisées en interne par Oracle. À titre d’exemple, une ligne
comprenant 3 colonnes stockant 30 octets de données utiles emploiera en moyenne 35 octets
d’espace dans le bloc et une ligne comprenant 15 colonnes stockant 145 octets de données utiles
emploiera en moyenne 160 octets d’espace dans le bloc.

b. Gestion de l’espace dans les blocs

L’espace libre à l’intérieur du segment peut être géré automatiquement ou


manuellement.

Dans le cas de la gestion "manuelle", pour chaque segment, Oracle gère une liste de blocs
disponibles pour l’insertion de lignes (freelist). La disponibilité ou la non-disponibilité d’un
bloc pour l’insertion est contrôlée par deux paramètres de la définition de la table :
PCTFREE et PCTUSED.

Dans le cas de la gestion "automatique", pour chaque segment, Oracle utilise une bitmap
afin de connaître le taux de remplissage de chaque bloc alloué au segment et en déduire
ceux dans lesquels il peut insérer des données. Dans ce cas, le paramètre PCTUSED est
sans objet. La gestion automatique est apparue en version 9.

La gestion automatique de l’espace dans les segments (Automatic Segment-Space


Management - ASSM) présente de nombreux avantages : facilité d’utilisation (pas de
paramètre PCTUSED à spécifier), meilleure utilisation de l’espace, meilleure concurrence
d’accès pour les insertions simultanées. La gestion automatique de l’espace dans les
segments est disponible uniquement dans les tablespaces gérés localement et spécifiée au
niveau du tablespace (pas du segment individuel) par la clause SEGMENT SPACE
MANAGEMENT AUTO (voir le chapitre Gestion des tablespaces et des fichiers de
données) ; elle est activée par défaut.

3 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

PCTFREE

Dans la définition d’une table, le paramètre PCTFREE spécifie le pourcentage de l’espace


du bloc laissé libre pour les modifications des lignes stockées dans le bloc :

La clause PCTFREE permet de ne pas remplir les blocs à 100 % et de conserver de l’espace
disponible à l’intérieur du bloc, pour les futures mises à jour des lignes stockées dans le
bloc. En effet, lorsqu’une ligne est modifiée, Oracle cherche à réaliser la modification en
conservant la ligne à l’intérieur du bloc où elle est stockée : cela ne pose pas de problème
si la longueur globale de la ligne diminue (remplacement de PIERRE par PAUL dans une
colonne) mais peut en poser si la ligne grossit (remplacement de PAUL par PIERRE dans une
colonne). Dans ce dernier cas, s’il n’y a pas suffisamment d’espace disponible à l’intérieur
du bloc, Oracle va déplacer la ligne dans un autre bloc avec des impacts négatifs sur les
performances que nous verrons dans la suite de cet ouvrage.

Gestion manuelle : PCTUSED

Dans la définition d’une table, en gestion manuelle uniquement, le paramètre PCTUSED


spécifie le pourcentage d’occupation auquel le bloc doit redescendre avant de redevenir
candidat à l’insertion :

Lorsque le bloc atteint un taux de remplissage correspondant à la clause PCTFREE, aucune


insertion n’est possible avant que de l’espace dans le bloc soit libéré, par suppression de
ligne ou diminution de la taille d’une ligne lors d’une modification. Le paramètre PCTUSED
permet de contrôler le moment où le bloc redeviendra candidat à l’insertion, suite à la
libération d’espace. Ce paramètre permet d’éviter que le bloc ne redevienne
immédiatement candidat à l’insertion dès que le moindre octet se libère, d’une part, car
l’espace libéré n’est peut-être pas suffisant pour réellement insérer une ligne et d’autre
part, car le bloc risque de redevenir non disponible dès la première insertion ; or, cette
gestion interne du bloc (disponible ou non pour l’insertion) est coûteuse en temps de
traitement. PCTUSED va donc permettre d’attendre que suffisamment d’espace ait été
libéré dans le bloc avant d’autoriser de nouvelles insertions dans le bloc.

Gestion automatique

4 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

En gestion automatique, Oracle utilise une bitmap pour connaître le taux de remplissage
de chaque bloc alloué au segment : 0 % d’espace libre (plein), entre 0 et 25 % d’espace
libre, entre 25 et 50 % d’espace libre, entre 50 et 75 % d’espace libre, entre 75 et 100 %
d’espace libre.

Lors de l’insertion d’une nouvelle ligne, Oracle utilisera la bitmap pour déterminer dans
quel bloc il peut insérer la ligne.

Dans la suite de ce chapitre, nous considérerons que la gestion automatique est utilisée. Nous
n’évoquerons pas PCTUSED et ne donnerons aucun conseil sur sa valeur.

c. Compression des données dans les blocs

Depuis Oracle9i Release 2, il est possible de compresser les données dans les blocs des
tables.

Avant la version 11, la compression s’effectue uniquement au moment de la création du


bloc, lors d’opérations comme la création d’une table à partir d’une requête (ordre SQL
CREATE TABLE ... AS SELECT), la reconstruction d’une table (ordre SQL ALTER TABLE ...
MOVE) ou les insertions en chemin direct (ordre SQL INSERT /*+ APPEND */ ...). Pour les
insertions ou modifications individuelles ultérieures (ordres SQL INSERT et UPDATE), les
données ne sont pas compressées. Dans ce cas, la compression est plutôt destinée à des
tables accédées en lecture, une fois qu’elles ont été construites ou reconstruites (par
exemple, dans une base décisionnelle).

Depuis la version 11, il est possible d’activer la compression pour toutes les opérations, y
compris les insertions ou modifications individuelles. Ce type de compression peut donc
aussi être utilisé dans une base transactionnelle. Cette fonctionnalité, intitulé OLTP Table
Compression, nécessite l’option Advanced Compression.

Oracle compresse les données au niveau du bloc en factorisant dans une table de
symboles, les valeurs répétées stockées dans le bloc. Un exemple est donné à la section
Réorganiser le stockage d’une table.

2. Le ROWID

Le ROWID est une colonne virtuelle présente dans chaque table qui donne l’adresse
physique de stockage de la ligne. Cette colonne virtuelle peut être interrogée comme les
autres colonnes de la table :

SQL> SELECT ROWID, numero, nom, prenom FROM adherent;


SQL> UPDATE adherent SET prenom = ’Olivier’
2 WHERE ROWID = ’AAAER2AACAAADdiAAA’;

Le ROWID permet de localiser physiquement la ligne ; il est utilisé en interne par Oracle
dans les index. S’il est connu, c’est le moyen le plus rapide pour accéder à une ligne.

Dans la structure interne du ROWID, Oracle a toutes les informations nécessaires à la


localisation physique de la ligne dans un fichier de données (fichier, numéro de bloc,
position dans le bloc). Un ROWID n’est pas directement compréhensible ; par contre, le

5 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

package DBMS_ROWID offre plusieurs fonctions qui permettent d’extraire les différentes
composantes du ROWID.

Utiliser le ROWID dans une application (dans les clauses WHERE des ordres SQL) se révèle
très intéressant du point de vue des performances : Oracle obtient directement l’adresse
physique de la ligne à lire ou modifier, sans devoir lire toute la table ni passer par un
index.

Le ROWID d’une ligne ne change jamais, tant que la ligne n’est pas supprimée. Modifier
une ligne ne change pas son ROWID puisque la ligne est, a priori, modifiée à l’intérieur du
bloc où elle a été insérée ; ce sera aussi le cas si la ligne est migrée vers un autre bloc par
manque d’espace disponible (ce qui n’est pas bénéfique comme nous le verrons ci-après).

3. Chaînage et migration

En règle générale, une ligne d’une table est stockée en totalité à l’intérieur d’un bloc.
Pour lire la ligne, Oracle n’a besoin de lire qu’un seul bloc.

Si la ligne est intrinsèquement trop grande pour tenir dans un seul bloc, Oracle la stocke
dans plusieurs blocs chaînés par des pointeurs : c’est le phénomène de chaînage d’une
ligne. Pour lire cette ligne, Oracle a alors besoin de lire plusieurs blocs.

Si une ligne grandit suite à une modification, et qu’il ne reste plus suffisamment d’espace
libre dans le bloc, Oracle déplace la ligne dans un autre bloc pointé par l’en-tête de la
ligne resté dans le bloc d’origine : c’est le phénomène de migration d’une ligne. Le ROWID
de la ligne modifiée et migrée n’a pas changé, mais pour lire cette ligne, Oracle a besoin
de lire deux blocs, ce qui dégrade les performances des accès par index. L’intérêt de cette
technique est qu’Oracle n’a pas besoin de modifier le ROWID de la ligne dans les index lors
d’une mise à jour de la ligne.

Le phénomène de chaînage est difficilement évitable, sauf en augmentant la taille des


blocs. Il faut donc y penser lors de la création de la base de données ou du tablespace.
Cela peut être insuffisant pour les très grandes lignes.

Le phénomène de migration peut (et même doit) être évité, en laissant suffisamment
d’espace disponible dans les blocs pour les mises à jour. Le paramètre PCTFREE sera donc
positionné avec soin sur les tables pour lesquelles la taille des lignes insérées est
sensiblement inférieure à la taille des lignes après modification(s).

4. Spécifier le stockage d’une table

Le stockage d’une table peut être spécifié lors de la création de la table, dans l’ordre SQL
CREATE TABLE.

Syntaxe simplifiée

CREATE TABLE nom_table


(spécification des colonnes)
[ TABLESPACE nom_tablespace ]
[ PCTFREE valeur ]
[ PCTUSED valeur ]
[ clause_stockage ]

6 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

[ NOCOMPRESS | COMPRESS [ FOR { ALL | DIRECT_LOAD } OPERATIONS ]]


[ LOGGING | NOLOGGING ] ;
- clause_stockage
STORAGE ( [ INITIAL valeur [K|M] ]
[ NEXT valeur [K|M] ]
[ MINEXTENTS valeur ]
[ MAXEXTENTS { valeur | UNLIMITED } ]
[ PCTINCREASE valeur ] )

Exemple :

CREATE TABLE adherent


(numero NUMBER(6),
nom VARCHAR2(40),
prenom VARCHAR2(30))
TABLESPACE data
PCTFREE 30
STORAGE ( INITIAL 10M ) ;

Les clauses TABLESPACE et STORAGE ont déjà été présentées au chapitre Gestion des
tablespaces et des fichiers de données. N’oubliez pas que la clause STORAGE est traitée
différemment selon que le tablespace est géré par le dictionnaire ou localement. Dans un
tablespace géré localement, seule l’option INITIAL est utile.

La clause PCTFREE donne la valeur du PCTFREE (entre 0 et 99, 10 par défaut).

La clause PCTUSED donne la valeur du PCTUSED (entre 0 et 99, 40 par défaut). Cette
clause est ignorée si la table est stockée dans un tablespace géré localement avec une
gestion automatique de l’espace dans les segments.

Par définition, PCTFREE+PCTUSED doit être strictement inférieur à 100.

La clause COMPRESS permet de compresser les données dans les blocs. L’option
DIRECT_LOAD indique que les blocs sont compressés, uniquement lors des opérations de
chargement direct (création de la table à partir d’une sous-requête, reconstruction de la
table ou chargement par des insertions en chemin direct) ; c’est la valeur par défaut.
L’option ALL indique que les blocs sont compressés pour toutes les opérations (y compris
les insertions ou modifications individuelles). Par défaut, la table hérite de l’option
COMPRESS ou NOCOMPRESS, éventuellement définie au niveau du tablespace dans lequel
elle est stockée.

La clause NOLOGGING permet de ne pas journaliser certaines opérations effectuées sur la


table (création à partir d’une sous-requête et insertion en chemin direct
essentiellement) ; les mises à jour individuelles sont, par contre, toujours journalisées. La
clause NOLOGGING est sans effet si la table est stockée dans un tablespace défini en mode
FORCE LOGGING, ou si la base de données elle-même est en mode FORCE LOGGING. Par
défaut, la table hérite de l’option LOGGING ou NOLOGGING, éventuellement définie au
niveau du tablespace dans lequel elle est stockée. La clause NOLOGGING est intéressante
pour améliorer les performances de certaines opérations mais rend la table irrécupérable
en cas d’incident ; après une opération NOLOGGING, il est souvent pertinent de réaliser
une sauvegarde de la base de données. L’ordre SQL ALTER TABLEpeut être utilisé pour
modifier certaines caractéristiques du stockage de la table.

Syntaxe simplifiée

7 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

ALTER TABLE nom_table


[ PCTFREE valeur ]
[ PCTUSED valeur ]
[ NOCOMPRESS | COMPRESS [ FOR { ALL | DIRECT_LOAD } OPERATIONS ] ]
[ LOGGING | NOLOGGING ]
[ clause_stockage_restreinte ] ;
clause_stockage_restreinte
STORAGE ( [ NEXT valeur [K|M] ]
[ MAXEXTENTS { valeur | UNLIMITED } ]
[ PCTINCREASE valeur ] )

L’ordre SQL ALTER TABLE n’a pas d’effet rétroactif sur le stockage déjà alloué à la table.
Il n’est donc pas possible, de cette manière, de changer la table de tablespace, de
modifier l’espace initialement alloué à la table ou le remplissage ou la compression des
blocs déjà utilisés.

Les caractéristiques modifiées sont prises en compte uniquement pour les futures
opérations. Plus tard, nous étudierons la clause MOVE de l’ordre SQL ALTER TABLE qui
permet de reconstruire physiquement le stockage d’une table.

5. Recommandations pour le stockage des tables


a. Vue d’ensemble

La recommandation numéro un est de stocker les tables dans un ou plusieurs tablespaces


dédiés, de préférence gérés localement (c’est le cas par défaut) avec une gestion
automatique de l’espace dans les segments (c’est le cas par défaut).

Si cette recommandation numéro un est respectée, vous allez bénéficier de nombreux


mécanismes de gestion automatique du stockage qui permettent éventuellement de ne
rien faire de plus. Dans ce cas, utilisez de préférence des tablespaces gérés localement
avec une gestion automatique de la taille des extensions (EXTENT MANAGEMENT LOCAL
AUTOALLOCATE, c’est le cas par défaut).

Néanmoins, si vous le souhaitez ou le pouvez, deux recommandations supplémentaires


peuvent être étudiées, au moins pour les tables les plus importantes de l’application :

• recommandation numéro deux : régler PCTFREE avec soin (voir Estimation de


PCTFREE) ;
• recommandation numéro trois : allouer un espace initial à la table, adapté à la
volumétrie estimée à une échéance donnée, si possible lointaine (6 mois, 1 an, 2
ans ou plus).

Si vous souhaitez contrôler plus précisément le stockage des tables (ou de certaines
tables), vous pouvez utiliser des tablespaces gérés localement avec une gestion uniforme
de la taille des extensions (EXTENT MANAGEMENT LOCAL UNIFORM) et/ou spécifier avec
soin l’option INITIAL de la clause STORAGE.

L’idée est de choisir des caractéristiques de stockage adaptées à la nature de la table


(petite, volumineuse, statique, à croissance régulière, etc.) et d’anticiper à une échéance
suffisamment lointaine pour être tranquille pendant quelque temps, et donc avoir le
temps nécessaire pour réagir si l’estimation initiale est mauvaise.

8 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Le fait qu’une table soit stockée dans un grand nombre d’extensions ne pose pas de problème du
point de vue des performances.

Par ailleurs, il ne faut pas hésiter à dédier des tablespaces au stockage des tables
volumineuses.

Dans un tablespace géré localement avec une gestion automatique de l’espace dans les segments,
les extensions doivent avoir une taille d’au moins 5 blocs.

b. Estimer la volumétrie d’une table à une échéance donnée

La méthode la plus simple (et la plus pragmatique) pour estimer la volumétrie d’une table
à une échéance donnée consiste à :

• estimer le nombre de lignes attendues ;


• créer la table dans les conditions d’exploitation (taille de bloc et PCTFREE
notamment) ;
• charger la table avec un jeu de données représentatives ;
• calculer le nombre de blocs occupés par ce jeu d’essai (par exemple à partir des
statistiques de la table ou à l’aide du package DBMS_SPACE - voir ci-après) ;
• en déduire le nombre de blocs pour le nombre de lignes attendues (règle de trois).

Cette méthode ne donne qu’une estimation, pas un résultat exact à l’octet près, car il y a
de nombreuses incertitudes :

• sur le nombre de lignes estimé à l’échéance (N +/- 10% par exemple) ;


• sur la représentativité du jeu de données, notamment sur la longueur moyenne des
données saisies (le nom du client stocké sous la forme d’un VARCHAR2(80)
comprendra-t-il en moyenne 40 caractères, 50, 60 ?).

Supposons par exemple que la table ADHERENT (schéma DIANE) ait été chargée avec
10 000 lignes et qu’elle doive en contenir 1 000 000 à une échéance de 2 ans. Nous
pouvons réaliser le calcul suivant :

SQL> EXEC dbms_stats.gather_table_stats(’DIANE’,’ADHERENT’)


Procédure PL/SQL terminée avec succès.

SQL> SELECT blocks FROM dba_tables


2 WHERE table_name=’ADHERENT’;
BLOCKS
----------
138

SQL> SELECT 138/10000*1000000 estimation FROM dual;


ESTIMATION
----------
13800

Le jeu de données utilise 138 blocs, donc, par règle de trois, nous pouvons estimer que la
table utilisera 13 800 blocs dans deux ans.

9 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

L’utilisation du package DBMS_STATS sera présenté à la section Superviser l’espace occupé


par une table.

En production, un calcul de ce genre peut être effectué à intervalles réguliers pour voir la
tendance et vérifier si les hypothèses de départ étaient bonnes.

c. Estimation de PCTFREE
Avec calcul

La valeur optimale de PCTFREE peut être estimée par la formule suivante :

PCTFREE = 100 x (1 -Ti / Tf)

Ti = taille moyenne initiale de la ligne en octets (au moment de l’insertion) ;

Tf = taille moyenne finale de la ligne en octets (après les mises à jour).

Les valeurs de Ti et Tf peuvent être estimées à partir des statistiques de la table


(AVG_ROW_LEN). Cette formule est surtout destinée à calculer la valeur de PCTFREE
concernant les tables pour lesquelles, la taille des lignes insérées initialement n’est pas
représentative de la taille finale de la ligne après modification(s). Pour les autres tables,
l’estimation sans calcul, présentée ci-après, peut être utilisée.

Sans calcul

Pour une table "statique" ou faisant uniquement l’objet d’insertions, mettre un PCTFREE
faible pour obtenir un bon remplissage des blocs (0 à 5). Pour une table faisant l’objet
d’insertion et de mises à jour, mettre un PCTFREE plus élevé pour éviter les phénomènes
de migration (10 à 50 en fonction du risque que les mises à jour fassent grossir plus ou
moins les lignes).

6. Surveiller l’utilisation d’une table

En version 9, Oracle a introduit une fonctionnalité permettant de mettre une table "sous
surveillance". Dans ce mode, Oracle trace le nombre approximatif d’ordres SQL INSERT,
UPDATE et DELETE exécutés sur la table.

En version 9, cette fonctionnalité devait être activée explicitement ; depuis la version 10,
les tables sont, par défaut, sous surveillance (sauf si le paramètre STATISTICS_LEVEL est
égal à BASIC, ce qui est déconseillé).

Ce mécanisme de surveillance est avant tout destiné à la fonctionnalité de calcul


automatique des statistiques ; les informations ainsi collectées permettent à Oracle de
déterminer les tables dont les statistiques ne sont plus à jour.

Ce mécanisme de surveillance peut aussi être utilisé pour analyser l’activité sur les tables
et identifier les tables les plus sollicitées en mise à jour ; ce sont les tables sur lesquelles
vous devez plus particulièrement porter votre attention en ce qui concerne le stockage
(réglage de PCTFREE notamment).

10 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Les informations sur les tables surveillées peuvent être consultées dans la vue DBA_TAB_
MODIFICATIONS (et consœurs).

Les principales colonnes de la vue sont les suivantes :

TABLE_OWNER : propriétaire de la table.

TABLE_NAME : nom de la table.

INSERTS : nombre approximatif de lignes insérées.

UPDATES : nombre approximatif de lignes modifiées.

DELETES : nombre approximatif de lignes supprimées.

TIMESTAMP : date/heure de la dernière mise à jour de la statistique.

TRUNCATED : indication pour savoir si la table a été tronquée (YES ou NO).

Les statistiques sur l’utilisation d’une table ne sont pas déversées en temps réel dans le
dictionnaire. Le délai annoncé est entre quelques secondes et plusieurs heures. La colonne
TIMESTAMP de la vue DBA_TAB_MODIFICATIONS permet de connaître la fraîcheur de
l’information.

Au besoin, la procédure FLUSH_DATABASE_MONITORING_INFO du packageDBMS_ STATS


peut être utilisée pour forcer la mise à jour immédiate du dictionnaire.

Il faut bien noter que les statistiques de surveillance sont supprimées lors de la génération
des statistiques. Les statistiques de surveillance sont donc collectées et cumulées depuis
la dernière génération de statistiques sur la table (voir la colonne LAST_ANALYZED de la
vue DBA_TABLES).

Pour une bonne analyse, il est important de réaliser des relevés périodiques afin de voir
l’évolution de l’activité et identifier d’éventuelles périodes de pointes.

7. Superviser l’espace occupé par une table


a. Vue d’ensemble

Les vues DBA_SEGMENTS et DBA_EXTENTS présentées au chapitre Gestion des tablespaces


et des fichiers de données permettent de voir l’espace global alloué à la table, mais elles
ne donnent pas d’informations sur le nombre de blocs réellement utilisés.

Pour chaque table (et plus généralement chaque segment), Oracle connaît le dernier bloc
utilisé par la table : c’est la high water mark (HWM - "ligne de plus hautes eaux").

La HWM augmente lors des insertions mais ne diminue pas lors des suppressions :

11 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

La HWM permet donc de connaître le nombre total maximum de blocs utilisés par la table
dans toute son existence, mais pas le nombre de blocs actuellement utilisés, ni leur
remplissage.

La HWM marque pour Oracle l’emplacement du dernier bloc où il est susceptible de


trouver une ligne ; au-delà de la HWM, une seule chose est sûre, il n’y a pas de ligne.
Lorsque Oracle réalise un parcours complet de la table, il ne parcourt pas tous les blocs
alloués à la table mais uniquement ceux situés sous la HWM.

Pour obtenir des informations plus détaillées sur le stockage d’une table, vous pouvez
utiliser le package DBMS_SPACE. Ce dernier propose plusieurs procédures qui permettent
notamment de calculer des informations sur l’espace libre et l’espace utilisé à l’intérieur
d’un segment.

Par ailleurs, pour les besoins de l’optimiseur, Oracle calcule périodiquement des
statistiques sur les tables (et les index), à l’aide du package DBMS_STATS ; certaines de
ces statistiques donnent des informations relatives au stockage.

Pour obtenir des informations plus détaillées sur le stockage d’une table, vous pouvez
utiliser les statistiques de la table, générées par le package DBMS_STATS ou calculer des
informations à l’aide du package DBMS_SPACE.

b. Le package DBMS_SPACE

Le package DBMS_SPACE propose plusieurs procédures qui peuvent être utilisées pour
superviser le stockage d’une table (plus généralement d’un segment) :

FREE_BLOCKS : informations sur les blocs libres dans un segment dont l’espace est géré
manuellement.

SPACE_USAGE : informations sur l’occupation des blocs dans un segment dont l’espace est
géré automatiquement.

UNUSED_SPACE : informations sur les blocs inutilisés d’un segment.

Le package DBMS_SPACE possède d’autres procédures ou fonctions qui permettent


d’estimer la taille d’une table ou d’un index ou la tendance de croissance d’un segment.
Ces procédures et fonctions, plus complexes à utiliser, ne sont pas présentées dans cet
ouvrage. Par contre, nous présenterons leur utilisation à travers l’interface graphique du
Database Control.

Pour plus d’informations sur le package DBMS_SPACE, reportez-vous à la documentation


PL/SQL Packages and Types Reference.

Exemple :

12 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

SQL> SET SERVEROUTPUT ON


SQL> DECLARE
2 v_unformatted_blocks NUMBER;
3 v_unformatted_bytes NUMBER;
4 v_fs1_blocks NUMBER;
5 v_fs1_bytes NUMBER;
6 v_fs2_blocks NUMBER;
7 v_fs2_bytes NUMBER;
8 v_fs3_blocks NUMBER;
9 v_fs3_bytes NUMBER;
10 v_fs4_blocks NUMBER;
11 v_fs4_bytes NUMBER;
12 v_full_blocks NUMBER;
13 v_full_bytes NUMBER;
14 PROCEDURE p(v_texte VARCHAR2) IS
15 BEGIN
16 dbms_output.put_line(v_texte);
17 END;
18 BEGIN
19 dbms_space.space_usage
20 (
21 segment_owner => ’DIANE’,
22 segment_name => ’ADHERENT’,
23 segment_type => ’TABLE’,
24 unformatted_blocks => v_unformatted_blocks,
25 unformatted_bytes => v_unformatted_bytes,
26 fs1_blocks => v_fs1_blocks,
27 fs1_bytes => v_fs1_bytes,
28 fs2_blocks => v_fs2_blocks,
29 fs2_bytes => v_fs2_bytes,
30 fs3_blocks => v_fs3_blocks,
31 fs3_bytes => v_fs3_bytes,
32 fs4_blocks => v_fs4_blocks,
33 fs4_bytes => v_fs4_bytes,
34 full_blocks => v_full_blocks,
35 full_bytes => v_full_bytes
36 );
37 p(’Blocs :’);
38 p(’. Pleins = ’||v_full_blocks);
39 p(’. 0 à 25% d’’espace libre = ’||v_fs1_blocks);
40 p(’. 25 à 50% d’’espace libre = ’||v_fs2_blocks);
41 p(’. 50 à 75% d’’espace libre = ’||v_fs3_blocks);
42 p(’. 75 à 100% d’’espace libre = ’||v_fs4_blocks);
43 p(’. Non formatés = ’||v_unformatted_blocks);
44 END;
45 /
Blocs :
. Pleins = 128
. 0 à 25% d’espace libre = 0
. 25 à 50% d’espace libre = 40
. 50 à 75% d’espace libre = 4
. 75 à 100% d’espace libre = 33
. Non formatés =0
Procédure PL/SQL terminée avec succès.

SQL> DECLARE
2 v_total_blocks NUMBER;
3 v_total_bytes NUMBER;
4 v_unused_blocks NUMBER;
5 v_unused_bytes NUMBER;
6 v_last_extent_file NUMBER;
7 v_last_extent_block NUMBER;

13 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

8 v_last_used_block NUMBER;
9 PROCEDURE p(v_texte VARCHAR2) IS
10 BEGIN
11 dbms_output.put_line(v_texte);
12 END;
13 BEGIN
14 dbms_space.unused_space (
15 segment_owner => ’DIANE’,
16 segment_name => ’ADHERENT’,
17 segment_type => ’TABLE’,
18 total_blocks => v_total_blocks,
19 total_bytes => v_total_bytes,
20 unused_blocks => v_unused_blocks,
21 unused_bytes => v_unused_bytes,
22 last_used_extent_file_id => v_last_extent_file,
23 last_used_extent_block_id => v_last_extent_block,
24 last_used_block => v_last_used_block
25 );
26 p(’Blocs :’);
27 p(’. Total = ’||v_total_blocks);
28 p(’. Inutilisés = ’||v_unused_blocks);
29 p(’. Utilisés = ’||(v_total_blocks-v_unused_blocks));
30 END;
31 /
Blocs :
. Total = 224
. Inutilisés = 7
. Utilisés = 217
Procédure PL/SQL terminée avec succès.

SQL> SELECT blocks FROM dba_segments


2 WHERE segment_name=’ADHERENT’ AND owner=’DIANE’;
BLOCKS
------------
224

Sur cet exemple, nous voyons que la table ADHERENT a 224 blocs alloués. Sur ces 224
blocs, 217 sont utilisés (c’est la HWM) et 7 sont inutilisés (jamais aucun ligne insérée à
l’intérieur). Sur les blocs utilisés, il y en a 128 qui sont pleins, 40 qui ont entre 25 et 50%
d’espace libre, 4 qui ont entre 50 et 75% d’espace libres et 33 qui ont entre 75 et 100%
d’espace libre, soit un total de 205 blocs. Les 12 blocs manquants pour arriver à 217 sont
des blocs de bitmap utilisés pour la gestion automatique (ils ne sont pas comptabilisés par
la procédure SPACE_USAGE).

c. Les statistiques sur une table

La procédure GATHER_TABLE_STATS du package DBMS_STATS permet de calculer des


statistiques sur une table.

Cette procédure a deux paramètres obligatoires en entrée :

ownname : Nom du schéma propriétaire de la table.

tabname : Nom de la table.

Exemple :

EXECUTE dbms_stats.gather_table_stats(’DIANE’,’ADHERENT’)

14 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

La procédure GATHER_TABLE_STATS a beaucoup d’autres paramètres dont la valeur par


défaut est généralement adaptée.

Au point Les statistiques et l’optimiseur Oracle, nous verrons que les statistiques sont
calculées automatiquement par Oracle à intervalles réguliers. En temps normal, il n’est
donc pas nécessaire d’utiliser cette procédure. Générer manuellement des statistiques
peut, par contre, s’avérer utile si vous venez de créer et de charger une table, ou après
une mise à jour massive des données d’une table (insertion, modification, suppression).

Le calcul de statistiques est effectué sur un échantillon des données. La taille de


l’échantillon est choisie automatiquement par Oracle en fonction des caractéristiques de
la table (au besoin, la taille de l’échantillon peut être spécifiée grâce au paramètre
estimate_percent).

Historiquement, les statistiques peuvent aussi être calculées à l’aide des clauses COMPUTE ou
ESTIMATE de l’ordre SQL ANALYZE TABLE. Cette possibilité est maintenue pour des raisons de
compatibilité ascendante. Pour calculer les statistiques sur les tables et les index, il faut utiliser le
package DBMS_STATS (depuis Oracle8i).

Les statistiques d’une table peuvent être consultées dans la vueDBA_TABLES (et
"consœurs") :

NUM_ROWS : Nombre de lignes dans la table.

BLOCKS : Nombre de blocs sous la High Water Mark (HWM).

AVG_ROW_LEN : Longueur moyenne d’une ligne, y compris les informations d’en-tête.

SAMPLE_SIZE : Nombre de lignes dans l’échantillon utilisé pour le calcul des statistiques.

LAST_ANALYZED : Date/heure de la dernière analyse de la table.

La valeur BLOCKS est toujours exacte, même si les statistiques ne sont pas calculées sur la totalité
de la table.

Exemple :

SQL> EXEC dbms_stats.gather_table_stats(’DIANE’,’ADHERENT’)


Procédure PL/SQL terminée avec succès.

SQL> SELECT num_rows,blocks,avg_row_len,sample_size,


2 TO_CHAR(last_analyzed,’DD/MM HH24:MI’) last_analyzed
3 FROM dba_tables WHERE table_name=’ADHERENT’ and owner=’DIANE’;
NUM_ROWS BLOCKS AVG_ROW_LEN SAMPLE_SIZE LAST_ANALYZED
---------- ---------- ----------- ----------- -------------
11488 217 91 11488 20/07 15:47

Nous retrouvons les 217 blocs utilisés, calculés à l’aide du package DBMS_SPACE.

15 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

d. Problèmes possibles sur le stockage

Les problèmes possibles sur le stockage d’une table sont les suivants :

• espace inutilisé alloué à une table ;


• faible taux d’occupation moyen des blocs.

Espace inutilisé alloué à une table

Il y a de l’espace inutilisé alloué à la table si le nombre de blocs occupés (sous la HWM) est
faible par rapport au nombre de blocs alloués, et si la table ne va plus grossir (ou peu).

Le nombre de blocs occupés est donné par la valeur de la colonne BLOCKS de la vue
DBA_TABLES (ou par un calcul à l’aide du package DBMS_SPACE) et le nombre de blocs
alloués par la valeur de la colonne BLOCKS de la vue DBA_SEGMENTS.

Exemple :

SQL> SELECT t.blocks "occupés",s.blocks "alloués"


2 FROM dba_tables t, dba_segments s
3 WHERE s.segment_name=t.table_name
4 AND s.owner=t.owner
5 AND t.table_name=’ADHERENT’ AND t.owner=’DIANE’;

occupés alloués
---------- ----------
217 224

Ce premier problème n’a pas d’incidence sur les performances (les blocs au-delà de la
HWM ne sont jamais lus) ; il conduit juste à un gaspillage d’espace disque.

Faible taux d’occupation moyen des blocs

Pour les tables dont l’espace est géré automatiquement, le taux d’occupation moyen des
blocs peut être analysé à l’aide du résultat donné par la procédure SPACE_USAGE du
package DBMS_SPACE.

Exemple :

Blocs :
. Pleins = 71
. 0 à 25% d’espace libre = 0
. 25 à 50% d’espace libre = 38
. 50 à 75% d’espace libre = 31
. 75 à 100% d’espace libre = 65
. Non formatés =0

Dans cet exemple, nous voyons que la table a 71 blocs pleins, 38 blocs moyennement
remplis et 96 faiblement remplis.

Si la proportion de blocs moyennement remplis ou faiblement remplis est importante, si


les lignes actuelles ne vont pas grossir, et si peu de nouvelles lignes vont être insérées,
nous pouvons considérer qu’il y a un problème de remplissage des blocs.

16 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Ce mauvais remplissage des blocs peut être lié à une valeur inadaptée de PCTFREE ou à
une suppression importante de données.

Ce deuxième problème a des incidences sur les performances et sur l’utilisation de


l’espace dans le Database Buffer Cache. Pour un nombre de lignes donné, un taux de
remplissage élevé nécessite moins de blocs pour le stockage, donc moins de blocs à lire et
moins de blocs dans le Database Buffer Cache.

8. Détecter les problèmes de migration ou de chaînage

La clause LIST CHAINED ROWS de l’ordre SQL ANALYZE TABLE permet d’identifier les lignes
migrées ou chaînées.

Syntaxe

ANALYZE TABLE nom_table LIST CHAINED ROWS;

Au préalable, la table CHAINED_ROWS doit être créée à l’aide du scriptutlchain.sql, qui se


trouve dans le répertoire %ORACLE_HOME%\rdbms\admin ou $ORACLE_
HOME/rdbms/admin. Après exécution de l’ordre SQL ANALYZE, cette table contient les
ROWID des lignes migrées ou chaînées.

Exemple :

SQL> @?\rdbms\admin\utlchain.sql
Table créée.

SQL> ANALYZE TABLE diane.adherent LIST CHAINED ROWS;


Table analysée.

SQL> SELECT COUNT(head_rowid) FROM chained_rows


2 WHERE table_name=’ADHERENT’ AND owner_name=’DIANE’;
COUNT(HEAD_ROWID)
-----------------
16

SQL> SELECT head_rowid FROM chained_rows


2 WHERE table_name=’ADHERENT’ AND owner_name=’DIANE’
3 AND ROWNUM = 1;
HEAD_ROWID
------------------
AAACmIAAKAAAA3sAAf

SQL> SELECT * FROM diane.adherent


2 WHERE ROWID = ’AAACmIAAKAAAA3sAAf’;
...

La table CHAINED_ROWS contient notamment les colonnes suivantes :

OWNER_NAME : Nom du schéma propriétaire de la table analysée.

TABLE_NAME : Nom de la table analysée.

HEAD_ROWID : ROWID de la ligne qui a un problème de migration ou de chaîne.

17 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

ANALYZE_TIMESTAMP : Date/heure de l’analyse.

Dans la table CHAINED_ROWS, l’analyse stocke le ROWID des lignes qui ont un problème de
chaînage ou de migration ; à l’aide d’une sous-requête, il est possible de lister les lignes
proprement dites. Les résultats s’accumulent dans la table ; lors d’une nouvelle analyse
d’une table préalablement analysée, il convient dont de supprimer de CHAINED_ROWS
l’ancien résultat ou d’utiliser la colonne ANALYZE_TIMESTAMP pour extraire le résultat.

Pour savoir s’il s’agit d’un problème de chaînage ou de migration, il faut interroger la
ligne. Si la ligne est plus courte que la taille du bloc, il s’agit d’un problème de migration
(la ligne pourrait tenir dans un bloc) ; si la ligne est plus longue que la taille du bloc, il
s’agit d’un problème de chaînage. La statistique AVG_ROW_LEN dans DBA_TABLES donne
une indication a priori ; si la longueur moyenne des lignes est assez largement inférieure à
la taille de bloc, il s’agit sûrement d’un problème de migration.

Déterminer à partir de quel pourcentage de lignes chaînées ou migrées il faut agir n’est
pas simple. Le pourcentage en soi n’est pas suffisant ; cela dépend aussi de l’activité qui
existe sur les lignes en question. S’il y a 90 % de lignes migrées ou chaînées mais que ces
lignes ne sont jamais interrogées, il n’y a pas de problème de performance ; à l’inverse,
s’il n’y a que 1 % de lignes migrées ou chaînées mais que ces lignes soient utilisées dans
toutes les requêtes, il risque d’y avoir un problème de performance.

9. Réorganiser le stockage d’une table


a. Vue d’ensemble

Les besoins de réorganisation d’une table sont variés :

• libérer de l’espace libre au-dessus de la HWM ;


• améliorer le taux de remplissage des blocs ;
• corriger un problème de migration ;
• réorganiser plus globalement le stockage de la table : changement de tablespace,
réduction du nombre d’extensions, changement de PCTFREE, etc.

Libérer de l’espace situé au-dessus de la HWM permet de récupérer de l’espace alloué à la


table mais jamais utilisé (et estimé jamais utilisable).

Améliorer le taux de remplissage des blocs permet aussi éventuellement de libérer de


l’espace inutilisé (l’espace libre des blocs), situé cette fois au-dessous de la HWM.

Plusieurs techniques sont à notre disposition pour réorganiser le stockage d’une table :

• ordre SQL ALTER TABLE ... DEALLOCATE UNUSED ;


• recréer la table / des lignes de la table ;
• export/import ;
• ordre SQL ALTER TABLE ... SHRINK SPACE ;
• ordre SQL ALTER TABLE ... MOVE.

Le tableau suivant résume les techniques envisageables (√) et indique lesquelles sont les
mieux adaptées (☺) à tel ou tel besoin :

18 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Export/
DEALLOCATE Recréer SHRINK MOVE
Import
Libérer de l’espace au-dessus de
☺ √ √ √ √
la HWM
Améliorer le taux de
√ √ ☺ ☺
remplissage des blocs
Corriger un problème de
☺ √ ☺
migration
Réorganisation plus globale √ √ ☺

À l’exception de l’ordre SQL ALTER TABLE ... DEALLOCATE UNUSED, les techniques citées
peuvent a priori être utilisés indifféremment pour régler les différents
problèmes ; néanmoins, certaines techniques sont mieux adaptées que d’autres à tel ou
tel besoin.

Historiquement, l’export/import est la technique de base pour les réorganisations un peu


massives ; c’est d’ailleurs toujours la bonne technique pour une réorganisation complète
de la base, notamment en cas de changement de la taille du bloc.

Pour le reste, les ordres SQL ALTER TABLE ... MOVE (depuis la 8i) et ALTER TABLE ...
SHRINK SPACE (depuis la 10) sont a priori les bons outils pour "reconstruire" une table.

b. L’ordre SQL ALTER TABLE ... DEALLOCATE UNUSED

L’ordre SQL ALTER TABLE ... DEALLOCATE UNUSED permet de libérer l’espace d’une table
situé au-dessus de la HWM.

Syntaxe

ALTER TABLE nom_table DEALLOCATE UNUSED [ KEEP valeur [K|M] ] ;

Exemple :

ALTER TABLE adherent DEALLOCATE UNUSED;


ALTER TABLE adherent DEALLOCATE UNUSED KEEP 0;
ALTER TABLE adherent DEALLOCATE UNUSED KEEP 1M;

L’option KEEP indique l’espace à conserver au-dessus de la HWM.

Sans clause KEEP, la taille initiale de la table est préservée : l’ordre ne libérera pas
d’espace si la HWM est inférieure à la taille initiale de la table (valeur de la colonne
INITIAL_EXTENT de la vue DBA_SEGMENTS).

Avec la clause KEEP, l’espace spécifié est conservé (éventuellement aucun avec KEEP 0) et
la taille initiale de la table, éventuellement ajustée dans le dictionnaire de données.

Par ailleurs, lorsque la table est stockée dans un tablespace géré localement, avec une
gestion uniforme des extensions, Oracle ne libérera que des extensions entières ; une
extension ne peut pas être "coupée" en deux. Si la table est stockée dans un tablespace
géré localement, avec une gestion automatique des extensions, Oracle peut "couper" une
extension en tenant compte des règles internes qu’il applique sur la taille des extensions.

19 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

L’espace libéré est rendu disponible pour d’autres segments (vue DBA_FREE_SPACE).

Cet ordre ne peut pas être utilisé pour libérer de l’espace au-dessous de la HWM (espace potentiel
libre suite à des suppressions de lignes, par exemple).

c. Recréer la table ou des lignes de la table

Supprimer la table puis la récréer permet évidemment d’en réorganiser le stockage.

Au préalable, il faudra sauvegarder les données dans une table de travail (ordre SQL
CREATE TABLE ... AS SELECT).

Cette méthode présente un inconvénient majeur : les objets dépendants sont supprimés
(triggers, contraintes, privilèges, index) ou invalidés (procédures stockées, vues). Il faut
donc bien penser à tout recréer avec la table.

Exemple :

-- créer une table de travail avec les bonnes clauses de stockage


CREATE TABLE temp
TABLESPACE ...
PCTFREE ...
STORAGE ...
AS SELECT * FROM adherent;
DROP TABLE adherent;
RENAME temp TO adherent;
-- recréer les objets dépendants

La table étant recréée avec de bonnes clauses de stockage, cette variante peut être
utilisée pour réorganiser complètement le stockage de la table, améliorer le taux de
remplissage des blocs, résoudre un problème de migration. Par contre, il faut penser à
recréer tous les objets dépendants et remettre les droits. De plus, le traitement peut être
long sur une table volumineuse.

Une première variante possible consiste à ne pas supprimer la table mais à la tronquer
(ordre SQL TRUNCATE TABLE) ; dans ce cas, les objets dépendants sont préservés.

Exemple :

CREATE TABLE temp AS SELECT * FROM adherent;


TRUNCATE TABLE adherent;
INSERT INTO adherent SELECT * FROM temp;

Cette variante offre moins de possibilités pour la réorganisation puisque la table n’est pas
recréée ; néanmoins, elle permet d’améliorer le taux de remplissage des blocs (de libérer
de l’espace sous la HWM) et de résoudre un problème de migration. La table n’étant pas
supprimée, il n’y a pas de difficulté avec les objets dépendants.

Par contre, il n’est pas possible de tronquer une table qui possède une contrainte de clé
primaire référencée par ailleurs ; il faut au préalable désactiver les contraintes de clé
étrangère concernées. De plus, lors de l’insertion, les contraintes d’intégrités sont

20 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

vérifiées et les triggers sont déclenchés, ce qui peut aussi poser des problèmes : là encore,
il convient de désactiver les contraintes et/ou les triggers qui posent des difficultés.

Une autre variante, utilisable pour corriger un problème de migration sur un petit nombre
de lignes, consiste à ne supprimer et recréer que les lignes fautives. La table n’étant pas
supprimée, il n’y a pas de problème avec les objets dépendants. Par contre, là encore,
cette méthode peut poser des difficultés avec les contraintes de clé étrangère et les
triggers.

Exemple :

CREATE TABLE temp AS SELECT * FROM adherent WHERE ...;


DELETE FROM TABLE adherent WHERE ...;
INSERT INTO adherent SELECT * FROM temp;

Pour ces différentes variantes, les outils d’export/import peuvent être utilisés pour
sauvegarder les données puis les réinsérer.

Dans la pratique, aucune de ces différentes variantes n’est vraiment simple à mettre en
œuvre. De plus, avec les deux premières variantes, la table n’est pas disponible pendant
la réorganisation.

d. L’ordre SQL ALTER TABLE ... SHRINK SPACE

L’ordre SQL ALTER TABLE ... SHRINK SPACE permet de compacter les lignes d’une table,
mais uniquement pour une table stockée dans un tablespace géré localement avec une
gestion automatique de l’espace dans les segments. Par défaut, Oracle compacte aussi le
segment, ajuste la HWM et libère l’espace ainsi récupéré.

Syntaxe

ALTER TABLE nom_table SHRINK SPACE [COMPACT] [CASCADE] ;

Avec l’option COMPACT, Oracle se contente de compacter les lignes, mais sans ajuster
la HWM ni libérer d’espace. L’exécution ultérieure d’un autre ordre SQL ALTER TABLE ...
SHRINK SPACE permettra de terminer l’opération.

L’option CASCADE permet de réaliser la même opération sur les segments dépendants de
la table, notamment les index.

Cette opération nécessite un déplacement des lignes et donc une modification du ROWID
des lignes déplacées. Par défaut, un tel déplacement n’est pas autorisé. Pour autoriser le
déplacement des lignes de la table, vous pouvez exécuter l’ordre SQL ALTER TABLE
nom_table ENABLE ROW MOVEMENT. Lors du déplacement des lignes et de la modification
du ROWID, Oracle met à jour les index.

L’opération de SHRINK peut être effectuée en ligne et des mises à jour parallèles sont
possibles ; un verrou exclusif est posé sur la table uniquement au moment du compactage
du segment proprement dit (déplacement de la HWM et libération de l’espace récupéré).

21 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Le compactage du segment peut poser des problèmes si des longues requêtes de lecture
sont en cours sur la table ; c’est la raison pour laquelle il est possible de dissocier les deux
phases du traitement.

Exemple

SQL> -- situation de départ


SQL> @dbms_space TEST
Blocs :
. Pleins = 216
. 0 à 25% d’espace libre = 0
. 25 à 50% d’espace libre = 0
. 50 à 75% d’espace libre = 0
. 75 à 100% d’espace libre = 0
. Non formatés =0
Blocs :
. Total = 256
. Inutilisés = 28
. Utilisés = 228

SQL> -- suppression d’une ligne sur deux


SQL> DELETE FROM test WHERE MOD(n,2) = 0;
7655 ligne(s) supprimée(s).
SQL> COMMIT;
Validation effectuée.

SQL> -- la table est pleine de trous !


SQL> @dbms_space TEST
Blocs :
. Pleins =0
. 0 à 25% d’espace libre = 0
. 25 à 50% d’espace libre = 2
. 50 à 75% d’espace libre = 214
. 75 à 100% d’espace libre = 0
. Non formatés =0
Blocs :
. Total = 256
. Inutilisés = 28
. Utilisés = 228

SQL> -- tentative de SHRINK


SQL> ALTER TABLE test SHRINK SPACE;
ALTER TABLE test SHRINK SPACE
*
ERREUR à la ligne 1 :
ORA-10636: ROW MOVEMENT is not enabled

SQL> -- => erreur


SQL> -- il faut autoriser le déplacement de ligne
SQL> ALTER TABLE test ENABLE ROW MOVEMENT;
Table modifiée.

SQL> -- cette fois c’est bon


SQL> ALTER TABLE test SHRINK SPACE;
Table modifiée.

SQL> @dbms_space TEST


Blocs :
. Pleins = 107
. 0 à 25% d’espace libre = 0
. 25 à 50% d’espace libre = 1

22 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

. 50 à 75% d’espace libre = 0


. 75 à 100% d’espace libre = 0
. Non formatés =0
Blocs :
. Total = 120
. Inutilisés = 2
. Utilisés = 118

Le script dbms_space.sql appelle les procédures SPACE_USAGE et UNUSED_SPACE du


package DBMS_SPACE pour afficher des informations sur l’espace utilisé dans un segment,
dont le nom est passé en paramètre.

Sur cet exemple, nous voyons que le SHRINK SPACE a bien compacté les lignes dans des
blocs et libéré l’espace.

e. L’ordre SQL ALTER TABLE ... MOVE

L’ordre SQL ALTER TABLE ... MOVEpermet de réorganiser complètement le stockage


physique d’une table sans la supprimer.

Syntaxe

ALTER TABLE nom_table MOVE


[ TABLESPACE nom_tablespace ]
[ PCTFREE valeur ]
[ clause_stockage ]
[ NOCOMPRESS | COMPRESS [ FOR { ALL | DIRECT_LOAD } OPERATIONS ] ]
[ LOGGING | NOLOGGING ] ;
- clause_stockage
STORAGE ( [ INITIAL valeur [K|M] ]
[ NEXT valeur [K|M] ]
[ MINEXTENTS valeur ]
[ MAXEXTENTS { valeur | UNLIMITED } ]
[ PCTINCREASE valeur ] )

Exemple :

ALTER TABLE adherent MOVE


PCTFREE 20
STORAGE (INITIAL 10M) ;

Les options sont les mêmes que celles de l’ordre SQL CREATE TABLE.L’ordre SQL ALTER
TABLE ... MOVE est très intéressant car toutes les options de stockage peuvent être
modifiées, dont le tablespace. De plus, les objets dépendants sont préservés.

Le principe mis en œuvre est de recopier physiquement les données des extensions
actuellement allouées vers une ou plusieurs nouvelles extensions allouées ailleurs. Les
extensions initiales sont libérées à la fin du traitement : la table initiale est donc intacte
en cas d’échec, mais il faut un espace disponible au moins égal à la taille initiale de la
table pendant la reconstruction.

Les lignes étant physiquement déplacées, les ROWID changent mais les index ne sont pas
mis à jour en temps réel par Oracle ; ils sont invalidés (statut UNUSABLE).Après avoir
reconstruit la table, il faudra reconstruire les index (ordre SQL ALTER INDEX ... REBUILD).

23 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

De même, les statistiques de la table deviennent invalides et de nouvelles statistiques


doivent être collectées.

Pendant le traitement, la table n’est pas disponible en mise à jour ; par contre, elle est
accessible en lecture (le segment initial est préservé). Cette technique de reconstruction
est plus simple à mettre en œuvre, et donc moins risquée, que les techniques de
recréation. C’est sans conteste LA technique à utiliser depuis la version 8i pour réorganiser
le stockage d’une table (ou d’un tablespace, en réalisant l’opération sur toutes les tables
du tablespace).

Exemple 1

• Situation de départ

SQL> SELECT tablespace_name,blocks,extents FROM dba_segments


2 WHERE segment_name=’ADHERENT’ AND owner=’DIANE’;
TABLESPACE_NAME BLOCKS EXTENTS
------------------------------ ---------- ----------
SYSTEM 768 21

SQL> SELECT num_rows,blocks,avg_row_len,sample_size,


2 TO_CHAR(last_analyzed,’DD/MM HH24:MI’) last_analyzed
3 FROM dba_tables WHERE table_name=’ADHERENT’ and owner=’DIANE’;
NUM_ROWS BLOCKS AVG_ROW_LEN SAMPLE_SIZE LAST_ANALYZED
---------- ---------- ----------- ----------- -------------
49907 659 86 49907 20/07 19:20

SQL> SELECT COUNT(head_rowid) FROM chained_rows


2 WHERE table_name=’ADHERENT’ AND owner_name=’DIANE’;
COUNT(HEAD_ROWID)
-----------------
5894

• Reconstruction

SQL> ALTER TABLE diane.adherent MOVE


2 TABLESPACE data
3 PCTFREE 20;

• Situation à l’arrivée (après calcul des statistiques et analyse des lignes chaînées ou
migrées)

SQL> SELECT tablespace_name,blocks,extents FROM dba_segments


2 WHERE segment_name=’ADHERENT’ AND owner=’DIANE’;
TABLESPACE_NAME BLOCKS EXTENTS
------------------------------ ---------- ----------
DATA 1280 1

SQL> SELECT num_rows,blocks,avg_row_len,sample_size,


2 TO_CHAR(last_analyzed,’DD/MM HH24:MI’) last_analyzed
3 FROM dba_tables WHERE table_name=’ADHERENT’ and owner=’DIANE’;
NUM_ROWS BLOCKS AVG_ROW_LEN SAMPLE_SIZE LAST_ANALYZED
---------- ---------- ----------- ----------- -------------
49907 751 86 49907 20/07 19:20

SQL> SELECT COUNT(head_rowid) FROM chained_rows


2 WHERE table_name=’ADHERENT’ AND owner_name=’DIANE’;
COUNT(HEAD_ROWID)

24 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

-----------------
0

Dans la situation de départ, la table ADHERENT présente deux problèmes majeurs :

• Elle est stockée dans le tablespace SYSTEM.


• Elle a plus de 10 % de lignes migrées (les lignes sont petites donc il ne s’agit pas
d’un problème de chaînage).

La table est donc reconstruite :

• dans le tablespace DATA ;


• avec un PCTFREE plus élevé.

Par ailleurs, le tablespace DATA est un tablespace géré localement avec une gestion
uniforme des extensions (10 Mo, soit 1 280 blocs) et une gestion automatique de l’espace
dans les segments ; il peut être mieux adapté à la volumétrie future de la table.

Exemple 2

• Situation de départ

SQL> SELECT num_rows,blocks,avg_row_len,sample_size,


2 TO_CHAR(last_analyzed,’DD/MM HH24:MI’) last_analyzed
3 FROM dba_tables WHERE table_name=’ADHERENT’ and owner=’DIANE’;
NUM_ROWS BLOCKS AVG_ROW_LEN SAMPLE_SIZE LAST_ANALYZED
---------- ---------- ----------- ----------- ------------
50966 602 86 50966 20/07 19:41

• Reconstruction avec compression

SQL> ALTER TABLE diane.adherent MOVE


2 COMPRESS;

• Situation à l’arrivée (après calcul des statistiques)

SQL> SELECT num_rows,blocks,avg_row_len,sample_size,


2 TO_CHAR(last_analyzed,’DD/MM HH24:MI’) last_analyzed
3 FROM dba_tables WHERE table_name=’ADHERENT’ and owner=’DIANE’;
NUM_ROWS BLOCKS AVG_ROW_LEN SAMPLE_SIZE LAST_ANALYZED
---------- ---------- ----------- ----------- ------------
50966 92 86 50966 20/07 19:41

Cet exemple illustre le gain, parfois spectaculaire, obtenu avec la compression.

10. Trouver des informations sur les tables

Plusieurs vues du dictionnaire de données permettent d’obtenir des informations sur les
tables :

• DBA_TABLES : informations sur les tables ;


• DBA_TAB_COLUMNS : informations sur les colonnes des tables ;
• DBA_SEGMENTS : informations sur les segments (dont ceux de type table) ;

25 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

• DBA_EXTENTS : informations sur les extensions allouées aux segments (dont ceux de
type table) ;
• DBA_TAB_MODIFICATIONS : informations sur les tables surveillées.

Les vues DBA_SEGMENTS et DBA_EXTENTS ont été présentées à la section Trouver des
informations sur les tablespaces et les fichiers de données du chapitre Gestion des
tablespaces et des fichiers de données.

Les colonnes intéressantes des différentes vues sont présentées ci-après.

DBA_TABLES

TABLE_NAME : Nom de la table.

OWNER : Propriétaire de la table.

TABLESPACE_NAME : Nom du tablespace dans lequel la table est stockée.

PCT_FREE : Valeur du PCTFREE.

NUM_ROWS : Nombre de lignes dans la table.

BLOCKS : Nombre de blocs sous la HWM.

AVG_ROW_LEN : Longueur moyenne d’une ligne en octets, en tenant compte des


informations de contrôle.

SAMPLE_SIZE : Taille de l’échantillon utilisé lors du calcul des statistiques.

LAST_ANALYZED : Date et heure de la dernière analyse réalisée sur la table.

LOGGING : Indique si le mode LOGGING est actif ou non pour la table (YES ou NO).

COMPRESSION : Indique si la table est compressée (DISABLED ou ENABLED).

TEMPORARY : Indique s’il s’agit d’une table temporaire (Y ou N).

ROW_MOVEMENT : Indique si le déplacement de lignes est autorisé (ENABLED ou


DISABLED).

DBA_TAB_COLUMNS

TABLE_NAME : Nom de la table.

OWNER : Propriétaire de la table.

COLUMN_NAME : Nom de la colonne.

DATA_TYPE : Type de données.

DATA_LENGTH : Longueur.

26 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

DATA_PRECISION : Précision.

DATA_SCALE : Échelle.

NULLABLE : Indique si la colonne accepte les valeurs NULL (Y ou N).

COLUMN_ID : Numéro de la colonne.

DATA_DEFAULT : Valeur par défaut de la colonne.

NUM_DISTINCT * : Nombre de valeurs distinctes dans la colonne.

NUM_NULLS * : Nombre de valeurs NULL dans la colonne.

AVG_COL_LEN * : Longueur moyenne de la colonne.

LAST_ANALYZED * : Taille de l’échantillon utilisé lors du calcul des statistiques.

SAMPLE_SIZE * : Date et heure de la dernière analyse réalisée sur la table.

* Statistiques sur les colonnes, calculées par défaut lorsque les statistiques sont générées
sur la table.

DBA_TAB_MODIFICATIONS

TABLE_OWNER : Propriétaire de la table.

TABLE_NAME : Nom de la table.

INSERTS : Nombre approximatif de lignes insérées.

UPDATES : Nombre approximatif de lignes modifiées.

DELETES : Nombre approximatif de lignes supprimées.

TIMESTAMP : Date/heure de la dernière mise à jour de la statistique.

TRUNCATED : Indique si la table a été tronquée (YES ou NO).

Gestion des index B-tree


1. Vue d’ensemble

Un index est une structure définie sur une ou plusieurs colonnes d’une table ; la (les)
colonne(s) constitue(nt) la clé de l’index.

L’index permet un accès rapide aux lignes de la table lors d’une recherche basée sur la clé
de l’index. La notion d’index est analogue à celle de l’index d’un livre : pour rechercher

27 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

un mot dans un livre, il est plus rapide de regarder d’abord dans l’index, ce dernier
donnant les numéros des pages qui contiennent le mot. Un index est physiquement et
logiquement indépendant de la table. Il peut être créé/supprimé sans affecter la table de
base (sauf impact sur les performances lorsque l’index est supprimé). Un index nécessite
son propre espace de stockage.

Les index sont automatiquement actualisés et utilisés par Oracle :

• utilisés lors des recherches si une clé d’index est mentionnée dans la clause WHERE
d’une requête ;
• actualisés à chaque mise à jour (INSERT, UPDATE, DELETE).

La présence ou l’absence d’un index est complètement transparente pour


l’application ; c’est Oracle qui utilise (ou non) les index automatiquement.

La maintenance des index dégrade les performances des mises à jour.

Un index peut être unique ou non unique :

• Unique: une valeur de la clé d’index n’est présente qu’une fois dans la table.
• Non unique : une valeur de la clé d’index peut être présente plusieurs fois dans la
table.

Oracle préconise de ne pas créer d’index unique explicitement mais de définir des
contraintes d’intégrité (PRIMARY KEY ou UNIQUE) pour lesquelles Oracle crée
automatiquement des index uniques. Les index non uniques, par contre, doivent être créés
explicitement.

Un index peut être composé (concaténé). Dans ce cas, la clé d’index contient plusieurs
colonnes de la table ; elles ne sont pas toujours adjacentes dans la table, ni forcément
placées dans le même ordre que dans la table.

Les valeurs NULL ne sont pas stockées dans les index B-tree et ne sont donc pas prises en
compte vis-à-vis de l’unicité : deux lignes de la table peuvent avoir la valeur NULL dans la
colonne concernée.

2. Structure d’un index B-tree


Structure générale

28 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Les données sont stockées dans des blocs Oracle.

Les blocs branches (branch blocks) contiennent des données qui pointent vers des blocs de
niveau inférieur. Les blocs branches permettent d’assurer un aiguillage d’un bloc racine
vers les blocs feuilles, en éliminant des branches à chaque niveau.

Les blocs feuilles (leaf blocks) contiennent les différentes valeurs de la clé d’index avec
les ROWID des lignes de la table correspondante. Pour un index unique, il existe un seul
ROWID par valeur de clé ; pour un index non unique, plusieurs ROWID sont possibles pour
chaque valeur de clé. Les blocs feuilles pointent vers les lignes de la table.

Lorsque l’index est utilisé pour rechercher une valeur de clé, le bloc racine est lu, puis le
bloc feuille de niveau inférieur correspondant à la branche qui contient la valeur de clé
est lu à son tour, et ainsi de suite jusqu’au bloc feuille qui contient la valeur de
clé ; associé à cette valeur de clé, Oracle va trouver le(s) ROWID(s) de la ou les lignes qui
contiennent la valeur de la clé et pouvoir ainsi les lire directement dans la table.

Les blocs feuilles sont doublement chaînés pour faciliter le parcours de l’index.

Les valeurs de clé NULL ne sont pas présentes dans l’index.

Dans les blocs feuilles d’un index non unique, les données sont triées sur la clé puis sur le
ROWID ; la valeur de la clé est répétée à chaque fois.

Structure d’un bloc

À l’image de la table, un bloc d’index comprend les données proprement dites et des
informations de contrôle (en-tête de bloc, en-tête de ligne, etc.).

Le remplissage du bloc, à la création de l’index uniquement, peut être contrôlé par le


paramètrePCTFREE. Le paramètre PCTFREE est donc important lors de la création d’un
index sur une colonne non vide. Dans les autres cas, ou pour la suite de la vie de l’index,
le paramètre n’est pas utilisé.

Il n’y a pas de PCTUSED pour les index.

29 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

3. Avantages et inconvénients des index B-tree


Avantages

L’index améliore la performance des requêtes (SELECT, UDATE et DELETE) qui utilisent la
clé de l’index dans la clause WHERE.

L’arbre est maintenu équilibré par Oracle. Dans "B-tree", "B" signifie balanced (balancé),
c’est-à-dire qu’Oracle s’arrange pour maintenir son arbre équilibré au fur et à mesure des
mises à jour de l’index. Pour cela, Oracle peut couper des blocs en cas de besoin (notion
de split).

En conséquence, toutes les valeurs de la clé dans les blocs feuilles sont situées à la même
profondeur de l’arbre et donc accessibles en parcourant le même nombre de blocs. La
recherche de n’importe quelle valeur de clé prend toujours à peu près le même temps.

Pourquoi un index B-tree est-il performant ?

Prenons l’exemple d’un index sur une date :

• La longueur d’une ligne de l’index est égale à 8 octets (longueur du type DATE) +
6 octets (longueur du ROWID) + quelques octets pour les informations de contrôle
(arrondi à 6 octets) = 20 octets.
• Avec une taille de bloc (DB_BLOCK_SIZE) de 8 Ko, l’espace disponible dans le bloc
est égal à 8 192 octets - taille de l’en-tête (entre 100 et 200 octets, prenons 192
octets pour notre exemple) = 8 000 octets, rempli à 90 % = 7 200 octets.
• Un bloc peut donc stocker environ 7 200 / 20 = 360 clés.
• Un arbre d’une profondeur de 3 peut donc gérer 360 x 360 x 360 = 466 millions de
clés.
• Pour retrouver une valeur parmi les 466 millions, 3 entrées/sorties sont suffisantes
dans l’index plus une entrée/sortie dans la table afin de lire chaque ligne.

De plus, si les colonnes utilisées dans les différentes clauses de la requête sont toutes
présentes dans l’index, Oracle n’a pas besoin d’accéder à la table. Si un index composé
existe sur les colonnes (NOM,PRENOM) de la table ADHERENT, la requête suivante
n’accède pas à la table :

SELECT nom, prenom FROM adherent


WHERE nom = ’HEURTEL’;
Inconvénients

Le premier inconvénient d’un index est qu’il nécessite un volume de stockage


important.Le second inconvénient d’un index est qu’il dégrade les performances des mises
à jour. Pour des mises à jour unitaires, cela ne devient sensible que si la table comprend
un grand nombre d’index ; pour une mise à jour massive, cette dégradation est sensible
dès l’existence du premier index. Ces deux inconvénients sont deux bonnes raisons pour ne
pas indexer toutes les colonnes d’une table.

30 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

4. Directives pour la création des index B-tree


a. Principes généraux

Les colonnes candidates à l’indexation sont les colonnes fréquemment présentes dans les
clauses WHERE, comme critère de sélection ou de jointure.

En complément, il faut s’assurer que les requêtes correspondantes sont sélectives et


ramènent moins de 5 à 10 % des lignes de la table. Cela implique donc, que les valeurs de
la colonne soient relativement uniques (beaucoup de valeurs distinctes), et que les
conditions qui les utilisent soient elles-mêmes sélectives. Il ne faut donc pas indexer les
colonnes ayant peu de valeurs distinctes (la colonne sexe par exemple).

Il est inutile d’indexer les petites tables.

Pour trouver les bonnes colonnes candidates à l’indexation, il faut analyser les requêtes
SELECT, UPDATE et DELETE, et rechercher les colonnes les plus fréquemment utilisées
dans les clauses WHERE (critère de sélection et jointure).

La performance d’un index dépend de sa sélectivité intrinsèque et de la sélectivité des


requêtes qui l’utilisent. La sélectivité peut être définie comme, le nombre moyen de
lignes ramenées par une requête divisé par le nombre total de lignes.

Prenons l’exemple de la table ADHERENT comprenant 100 000 personnes avec une
répartition homogène homme/femme. Considérons les clauses WHERE suivantes :

Clause WHERE Sélectivité


WHERE numero =12345 1 / 100 000 = 0,001 %
WHERE numero BETWEEN 1 AND 20000 20 000 / 100 000 = 20 %
WHERE sexe = ’F’ 50 000 / 100 000 = 50 %

Ces exemples montrent que la colonne NUMERO est intrinsèquement sélective mais que
certaines requêtes basées sur cette colonne peuvent ne pas l’être ; par contre, la colonne
SEXE n’est pas intrinsèquement sélective.

Une colonne ayant peu de valeurs distinctes est intrinsèquement non sélective. Parmi les
colonnes candidates à l’indexation, il faut donc identifier celles qui sont intrinsèquement
sélectives et utilisées dans des requêtes elles-mêmes sélectives ; une colonne sera
effectivement une bonne candidate à l’indexation si la sélectivité (de la colonne et des
requêtes qui l’utilisent) est inférieure à environ 5 à 10 %. Dans les grandes lignes, si une
requête utilisant un index ramène plus de 10 % des lignes, Oracle se révèlera plus
performant en réalisant un parcours complet de la table qu’en passant par l’index.

Cette règle des 5 à 10 % n’est pas en soi une garantie de performance effective de
l’index ; de nombreux autres facteurs entrent en ligne de compte. C’est néanmoins un bon
critère de départ, qu’il faut valider en réalisant des tests.

Parmi les colonnes candidates, il faudra d’abord identifier les colonnes qui sont
systématiquement présentes ensembles dans la clause WHERE : ce sont de bonnes
candidates à la création d’un index composé qui est généralement plus sélectif qu’un
index simple. En effet, si les colonnes C1 et C2 d’une table sont fréquemment utilisées

31 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

ensembles dans les clauses WHERE et qu’il existe 10 valeurs distinctes pour C1 (sélectivité
de 10 %) et 10 valeurs distinctes pour C2 (sélectivité de 10 %), la sélectivité théorique du
couple (C1,C2) est de 1 % (dans l’hypothèse où il n’y a pas de corrélation entre C1 et C2).

Indexer les petites tables ne sert à rien car le nombre minimum d’entrées/sorties lors d’un
accès par index est de 2 (1 entrée/sortie au minimum pour l’index et 1 entrée/sortie au
minimum pour la table). Or, grâce au paramètreDB_FILE_MULTIBLOCK_READ_COUNT
(DBFMRC ci-après), Oracle peut lire DBFMRC blocs en une entrée/sortie lors d’un parcours
complet de table. Donc, si la taille de la table est inférieure à DBFMRC blocs, un index est
moins performant que le parcours complet ; si la taille de la table est inférieure à 2 x
DBFMRC blocs, un index est aussi performant (mais pas plus) que le parcours complet.
Ainsi, en général, indexer des tables comprenant quelques dizaines de blocs n’apporte
rien.

Les valeurs NULL ne sont pas stockées dans les index B-tree ; donc, indexer une colonne
pour améliorer les recherches IS NULL ne sert à rien. Hormis les index uniques, il n’est
jamais certain qu’un index soit réellement performant ; il faut donc le tester. Lors des
tests sur les index, il ne faut pas oublier de vérifier si les index ne dégradent pas trop les
performances des mises à jour.

b. Compléments sur les index composés

L’ordre des colonnes est important dans un index composé. Un index composé est utilisé si
les colonnes de tête de la clé d’index sont présentes dans la condition.

Si un index composé existe sur les colonnes (NOM,PRENOM) de la table ADHERENT, les trois
requêtes suivantes utilisent l’index :

SELECT * FROM adherent


WHERE nom = ’HEURTEL’ AND prenom = ’Olivier’;
SELECT * FROM adherent
WHERE prenom = ’Olivier’ AND nom = ’HEURTEL’;
SELECT * FROM adherent
WHERE nom = ’HEURTEL’;

Par contre, la requête suivante n’utilise pas l’index :

SELECT * FROM adherent


WHERE prenom = ’Olivier’;

L’ordre des colonnes n’a pas d’importance dans la clause WHERE.

Dans certains cas, si la première colonne de l’index a très peu de valeurs distinctes (par exemple
2), Oracle est susceptible de subdiviser l’index en sous-index (un pour chaque valeur de la
première colonne) et de parcourir chaque sous-index.

Dans certaines situations, il peut être intéressant d’ajouter dans la clé d’index des
colonnes présentes dans la clause SELECT, pour éviter d’accéder à la table.

Pour la requête suivante, ajouter la colonne NUMERO_TELEPHONE dans l’index composé


qui existe sur les colonnes (NOM,PRENOM) permet d’éviter l’accès à la table

32 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

SELECT numero_telephone FROM adherent


WHERE nom = ’HEURTEL’ AND prenom = ’Olivier’;

Abuser de cette astuce et placer de nombreuses colonnes dans la clé d’index peut rendre l’index
moins performant. Plus la clé d’index est longue, moins il y a de clés par bloc, et plus l’index est
volumineux et profond, ce qui augmente le nombre d’entrées/sorties pour parcourir l’index.

c. S’assurer que les requêtes sont bien écrites

Par ailleurs, il faut s’assurer que l’écriture des requêtes n’empêche pas l’index d’être
utilisé.

Exemples de clauses WHERE où l’index présent sur la colonne nom n’est pas utilisé :

nom IS NULL

Les valeurs NULL ne sont pas dans l’index.

nom NOT IN(’DUPONT’,’DUPOND’)nom < > ’HEURTEL’

Les recherches "différent de" n’utilisent pas l’index.

nom LIKE ’%TEL’

Les recherches LIKE n’utilisent pas l’index si le début de la chaîne n’est pas connu
(recherches du type "contient", "se termine par").

SUBSTR(nom,1,1) =’H’

Et plus généralement, lorsqu’une fonction est appliquée à la colonne, ou que la colonne


est utilisée dans une expression.

Par contre, exemples de clauses WHERE où l’index est utilisé :

nom > ’HEURTEL’

Les recherches de type "inférieur", "supérieur", "entre" utilisent l’index.

nom LIKE ’H%’

Le début de la chaîne est connu.

Ce n’est pas parce qu’une requête n’empêche pas l’utilisation d’un index, que l’index est
réellement utilisé. C’est l’optimiseur Oracle qui décidera d’utiliser ou non un index, en fonction
des caractéristiques de la requête, de la table et des index (c’est un vaste sujet).

33 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

5. Spécifier le stockage d’un index


a. Index indépendant

Le stockage d’un index peut être spécifié lors de la création de l’index, dans l’ordre SQL
CREATE INDEX.

Syntaxe simplifiée

CREATE [UNIQUE] INDEX nom_index ON nom_table(liste_colonnes)


[ TABLESPACE nom_tablespace ]
[ PCTFREE valeur ]
[ clause_stockage ]
[ ONLINE ]
[ NOCOMPRESS | COMPRESS [n] ]
[ LOGGING | NOLOGGING ] ;
- clause_stockage
STORAGE ( [ INITIAL valeur [K|M] ]
[ NEXT valeur [K|M] ]
[ MINEXTENTS valeur ]
[ MAXEXTENTS { valeur | UNLIMITED } ]
[ PCTINCREASE valeur ] )

Exemple :

CREATE INDEX adherent$nom#prenom ON adherent(nom,prenom)


TABLESPACE indx
PCTFREE 20
STORAGE ( INITIAL 2M ) ;

Les clauses TABLESPACE et STORAGE ont déjà été présentées au chapitre Gestion des
tablespaces et des fichiers de données. N’oubliez pas que la clause STORAGE est traitée
différemment selon que le tablespace est géré par le dictionnaire ou localement. Dans un
tablespace géré localement, seule l’option INITIAL est utile.

La clause PCTFREE donne la valeur du PCTFREE (entre 0 et 99, 10 par défaut).

La clause ONLINE permet d’autoriser les mises à jour sur la table pendant la construction
de l’index.

La clause COMPRESS [n] permet de compresser la clé d’index, uniquement dans le cas d’un
index composé. Pour compresser la clé d’index, Oracle élimine les occurrences répétées
des valeurs des colonnes de la clé. L’option n permet de préciser le nombre de colonnes
de la clé à compresser. Par défaut, n est égal au nombre de colonnes moins un pour un
index unique et au nombre de colonnes pour un index non unique. Compresser la clé des
index composés peut permettre de réduire sensiblement la taille de l’index. Pour obtenir
un résultat optimal, il faut compresser sur la portion de tête de la clé comprenant le plus
grand nombre de répétitions (cette information peut être obtenue avec l’ordre SQL
ANALYZE INDEX ... VALIDATE STUCTURE présenté plus loin).

La clause NOLOGGING permet de ne pas journaliser la création de l’index ; les mises à jour
individuelles sont, par contre, toujours journalisées. Les considérations sont les mêmes
que pour une table (cf. Gestion des tables) mais un index est moins critique qu’une
table ; si un index n’est pas récupérable, il est toujours possible de le reconstruire.

34 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Il existe aussi un ordre SQL ALTER INDEX mais, comme pour une table, il n’a pas d’effet
rétroactif sur ce qui est déjà alloué ; généralement, en cas de besoin, l’index sera plutôt
reconstruit.

b. Index d’une contrainte de clé primaire ou unique

Le stockage de l’index d’une clé primaire ou unique peut être spécifié lors de la définition
de la contrainte grâce à l’option USING INDEX de la clause CONSTRAINT.

Syntaxe

CONSTRAINT nom_contrainte { PRIMARY KEY | UNIQUE } (liste_colonnes)


USING INDEX<$ICONSTRAINT;USING INDEX>
[ spécification_stockage | nom_index | (ordre_création_index) ]
- spécification_stockage
[ TABLESPACE nom_tablespace ]
[ PCTFREE valeur ]
[ clause_stockage ]
[ ONLINE ]
[ NOCOMPRESS | COMPRESS [n] ]
[ LOGGING | NOLOGGING ] ;

• nom_index : nom d’un index qui existe déjà.


• ordre_création_index : ordre SQL de création d’index tel que vu précédemment.

Exemple :

• Définition des clauses de stockage de l’index

ALTER TABLE adherent ADD CONSTRAINT adherent$pk PRIMARY KEY(numero)


USING INDEX
TABLESPACE indx
PCTFREE 0
STORAGE (INITIAL 2M) ;

• Spécification d’un index déjà existant

ALTER TABLE adherent ADD CONSTRAINT adherent$uk01


UNIQUE (nom,prenom,telephone)
USING INDEX adherent$ix01 ;

• Création complète de l’index

ALTER TABLE adherent ADD CONSTRAINT adherent$uk01


UNIQUE (nom,prenom,telephone)
USING INDEX
(
CREATE INDEX adherent$ix01
ON adherent(nom,prenom,telephone)
TABLESPACE indx
PCTFREE 25
STORAGE (INITIAL 10M)
);

Par défaut, lorsqu’une contrainte de clé primaire ou de clé unique est créée ou activée,
Oracle regarde s’il existe un index utilisable pour vérifier la contrainte. Cet index peut

35 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

être unique ou non unique, mais doit posséder une clé égale à ou commençant par la clé
de la contrainte. Si un tel index n’existe pas, Oracle crée un index unique pour vérifier la
contrainte, index dont la clé est égale à la clé de la contrainte. Dans ce cas, l’option
USING INDEX de la clause CONSTRAINT permet de spécifier les caractéristiques de stockage
de cet index.

Depuis Oracle9i, la clause USING INDEX peut :

• mentionner explicitement le nom d’un index à utiliser pour vérifier la contrainte ;


• inclure un ordre SQL CREATE INDEX pour créer explicitement l’index associé à la
contrainte.

Dans les deux cas, les autres options de la clause USING INDEX sont interdites.

L’index mentionné ou créé peut être unique ou non unique mais il doit être "compatible"
avec la contrainte de clé primaire ou unique. Si l’index est unique, la clé de l’index doit
être égale à la clé de la contrainte (mêmes colonnes, dans le même ordre). Si l’index est
non unique, la clé de l’index doit être égale à ou commencer par la clé de la contrainte.

Exemple :

CREATE INDEX adherent$ix01 ON adherent(nom,prenom,telephone)


TABLESPACE indx ;

ALTER TABLE adherent


ADD CONSTRAINT adherent$pk PRIMARY KEY (nom,prenom)
USING INDEX adherent$ix01 ;

Fonctionnellement, créer l’index avant la contrainte et le mentionner dans l’ordre de


création de la contrainte équivaut strictement à créer l’index dans l’ordre de définition de
la contrainte.

Utiliser une des deux clauses USING INDEX apparues dans Oracle9i permet :

• d’être plus explicite ;


• de désigner un index précis si plusieurs index peuvent être utilisés pour vérifier la
contrainte ;
• de créer un autre index que celui qui serait utilisé par défaut (avec une autre clé) ;
• si aucun index n’existe déjà, de créer un index avec un nom précis, sur une clé
précise, généralement plus "longue" que la clé de la contrainte ;
• de créer explicitement un index non unique (voir l’intérêt ci-après).

La vue DBA_CONSTRAINTScontient deux colonnes, INDEX_OWNER et INDEX_NAME, qui permettent


de faire le lien entre une contrainte de clé primaire ou de clé unique et son index associé (vue
DBA_INDEXES).

Par défaut, lorsqu’une clé primaire ou unique est supprimée :

• L’index associé est supprimé s’il est unique.


• L’index associé est conservé s’il est non unique.

36 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

L’origine de l’index (créé par Oracle, déjà existant, créé dans l’ordre de définition de la
contrainte) n’a pas d’impact.

Depuis Oracle9i, il est possible d’indiquer explicitement si l’index associé à une contrainte
supprimée doit être conservé ou supprimé.

Syntaxe

ALTER TABLE DROP CONSTRAINT { nom_contrainte | PRIMARY KEY }


KEEP INDEX | DROP INDEX ;

A priori, conserver un index unique lors de la suppression d’une contrainte de clé primaire
ou unique n’a pas de sens : l’unicité est toujours vérifiée au niveau de l’index.

L’approche par défaut d’Oracle est relativement logique. Si une contrainte de clé primaire
ou de clé unique est supprimée, c’est notamment que l’unicité n’est plus
souhaitée ; supprimer l’index associé est donc logique. Par contre, un index non unique ne
vérifie pas l’unicité et peut donc être conservé, même lorsque la contrainte est
supprimée.

La nouvelle clause est intéressante pour aller à l’encontre du fonctionnement par


défaut : supprimer un index qui serait conservé ou conserver un index qui serait supprimé.
Elle permet aussi d’être plus explicite et de ne pas se préoccuper du fonctionnement par
défaut.

Créer systématiquement des index non uniques pour gérer les contraintes de clé primaire et de clé
unique est intéressant, et laisse en tout état de cause le choix de conserver ou non l’index lors de
la suppression ou de la désactivation de la contrainte.

6. Recommandations pour le stockage des index


a. Vue d’ensemble

Les recommandations sont les mêmes que pour les tables (section Gestion des tables) :

• recommandation numéro un (fondamentale) : stocker les index dans un ou plusieurs


tablespaces dédiés, de préférence gérés localement (c’est le cas par défaut) avec
une gestion automatique de l’espace dans les segments (c’est le cas par défaut) ;
• recommandation numéro deux (moins importante) : régler PCTFREE avec soin (voir
Estimation de PCTFREE), au moins pour les index les plus importants ;
• recommandation numéro trois (moins importante) : allouer un espace initial à
l’index, adapté à la volumétrie estimée à une échéance donnée (pas forcément très
lointaine, car très souvent, les index sont reconstruits à intervalles réguliers).

Définir un index en spécifiant un INITIAL adapté à la volumétrie estimée de l’index, peut améliorer
la performance de création de l’index, en diminuant le nombre d’extensions allouées pendant
l’opération.

37 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

b. Estimer la volumétrie d’un index à une échéance donnée

Là encore, le plus simple et le plus pragmatique consiste à procéder comme pour une
table :

• estimer le nombre de lignes attendues ;


• créer l’index dans les conditions d’exploitation (taille de bloc et PCTFREE
notamment) ;
• charger la table avec un jeu de données représentatives ;
• calculer le nombre de blocs d’index occupés par ce jeu d’essai (par exemple, à
partir des statistiques de l’index ou à l’aide du package DBMS_SPACE, voir ci-
après) ;
• en déduire le nombre de blocs pour le nombre de lignes attendues (règle de trois).

Supposons, par exemple, que la table ADHERENT (schéma DIANE) ait été chargée avec
10 000 lignes et qu’elle doit en contenir 250 000 à une échéance de 6 mois. Nous pouvons
réaliser le calcul suivant pour un de ces index :

SQL> ANALYZE INDEX adherent$ix01 VALIDATE STRUCTURE;


Index analysé.

SQL> SELECT lf_blks+br_blks FROM index_stats


2 WHERE name=’ADHERENT$IX01’;
LF_BLKS+BR_BLKS
---------------
59

SQL> SELECT 59/10000*250000 estimation FROM dual;


ESTIMATION
----------
1475

L’index pour le jeu de données utilise 59 blocs, donc par règle de trois, nous pouvons
estimer que l’index utilisera 1 475 blocs dans 6 mois.

L’emploi de l’ordre SQL ANALYZE INDEX ... VALIDATE STRUCTURE est présenté plus loin.

c. Estimation de PCTFREE

Vous n’avez pas besoin de vous préoccuper de PCTFREE si la colonne indexée est vide lors
de la création de l’index. Pour mémoire, PCTFREE est pris en compte uniquement à la
création de l’index et n’est effectivement utilisé que si la colonne à indexer est non vide.

Vous pouvez positionner PCTFREE à une valeur faible (éventuellement 0) dans les cas
suivants :

• Si l’index est créé sur une colonne qui sera rarement mise à jour (ni UPDATE ni
INSERT).
• Si l’index est créé sur une colonne qui va continuer à faire l’objet d’insertions avec
des valeurs en dehors de la plage des valeurs actuelles (ces entrées d’index iront
dans de nouveaux blocs).

Dans le cas où l’index est créé sur une colonne non vide, l’objectif de PCTFREE est
simple : réserver de l’espace dans les blocs pour les éventuelles futures insertions de clés

38 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

dans les blocs d’index initialement utilisés (les clés sont triées dans les blocs feuilles). Si
pour une raison quelconque, les futures insertions de clés ne risquent pas de venir dans les
blocs déjà utilisés, il est possible de mettre un PCTFREE faible ou nul.

Vous devez par contre positionner PCTFREE à une valeur élevée dans les cas suivants :

• Si l’index est créé sur une colonne qui sera souvent mise à jour (UPDATE).
• Si l’index est créé sur une colonne qui va continuer à faire l’objet d’insertions avec
des valeurs appartenant à la plage des valeurs actuelles (ces entrées viendront
s’intercaler dans les blocs existants).

Dans ce cas, PCTFREE peut être estimé par la formule suivante :

PCTFREE = 100 x (1 -Ni / Nf)

Ni = nombre initial de lignes ;

Nf = nombre final de lignes (à une échéance donnée).

Nf est une valeur relativement arbitraire, Nf - Ni étant le nombre de lignes à insérer dans
l’index avant que tout l’espace laissé libre initialement soit occupé (statistiquement), et
que Oracle doit commencer à réorganiser son arbre d’index.

Une valeur arbitraire de PCTFREE peut être utilisée (10 à 20 %), sachant qu’il est facile de
superviser le stockage d’un index et de le reconstruire en cas de besoin.

Lorsqu’une clé d’index est modifiée, l’entrée correspondante est supprimée et recréée. Lorsque
des entrées sont supprimées dans un bloc d’index, l’espace libéré ne peut être réutilisé que pour
des entrées dont c’est la place (les données sont triées dans les blocs feuilles). Pour pouvoir
réutiliser un bloc et y placer des valeurs complètement différentes, il faut que le bloc soit
complètement vide.

7. Superviser l’espace occupé par un index


a. Vue d’ensemble

Là encore, vous trouverez de nombreuses similitudes avec les tables ...

Les vues DBA_SEGMENTS et DBA_EXTENTS présentées au chapitre Gestion des tablespaces


et des fichiers de données permettent de voir l’espace global alloué à l’index, mais elles
ne donnent pas d’informations sur le nombre de blocs réellement utilisés.

Pour obtenir des informations plus détaillées sur le stockage d’un index, vous pouvez :

• utiliser les informations calculées par le package DBMS_SPACE (voir le point Gestion
des tables) ;
• employer les statistiques générées par le package DBMS_STATS ;
• utiliser d’autres statistiques calculées par l’ordre SQL ANALYZE INDEX ... VALIDATE
STRUCTURE.

39 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Les statistiques générées par le package DBMS_STATS ne sont pas suffisantes pour réaliser
une analyse détaillée du stockage de l’index (mais elles sont suffisantes pour
l’optimiseur) ; nous ne les évoquerons donc, pas ici (description de la vue DBA_INDEXES au
point Trouver des informations sur les index).

Nous allons par contre, présenter l’utilisation de l’ordre SQL ANALYZE INDEX ... VALIDATE
STRUCTURE.

b. L’ordre SQL ANALYZE INDEX ... VALIDATE STRUCTURE

L’ordre SQL ANALYZE INDEX ... VALIDATE STRUCTURE permet de vérifier l’intégrité de
l’index et d’obtenir des informations détaillées sur le stockage de l’index.

Syntaxe

ANALYZE INDEX nom_index VALIDATE STRUCTURE;

Exemple :

ANALYZE INDEX adherent$ix01 VALIDATE STRUCTURE;

L’ordre SQL ANALYZE INDEX ... VALIDATE STRUCTURE ne vérifie pas la cohérence de
l’index vis-à-vis de la table ; pour vérifier une telle cohérence, il faut ajouter l’option
CASCADE. Le résultat peut être consulté dans la vue INDEX_STATS :

NAME : nom de l’index.

HEIGHT : hauteur de l’arbre.

BLOCKS : nombre de blocs alloués au segment.

LF_BLKS : nombre de blocs feuilles dans l’index.

BR_BLKS : nombre de blocs branches dans l’index.

LF_ROWS : nombre de lignes (valeurs) dans l’index.

DEL_LF_ROWS : nombre de lignes supprimées dans l’index.

PCT_USED : pourcentage de l’espace alloué à l’index qui est utilisé (entre 0 et 100).

OPT_CMPR_COUNT : Nombre de colonnes de la clé d’index à utiliser pour avoir une


compression optimale.

OPT_CMPR_PCTSAVE : Pourcentage d’espace qui peut être économisé en compressant la


clé d’index selon le nombre de colonnes indiqué.

La vue INDEX_STATS ne donne que le résultat du dernier ANALYZE INDEX ... VALIDATE STRUCTURE.

40 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Les statistiques générées par l’ordre SQL ANALYZE INDEX ... VALIDATE STRUCTURE ne sont
pas utilisées par l’optimiseur.

La somme LF_BLKS+BR_BLKS donne le nombre de blocs utilisés par l’index, c’est-à-dire le


nombre de blocs dans lequel il existe au moins une ligne ; PCT_USED donne le pourcentage
moyen d’occupation des blocs utilisés.

Exemple :

• Situation de départ (juste après la création de l’index)

SQL> SELECT height,lf_blks,br_blks,blocks,pct_used,


2 lf_rows,del_lf_rows
3 FROM index_stats WHERE name=’ADHERENT$IX01’;
HEIGHT LF_BLKS BR_BLKS BLOCKS PCT_USED LF_ROWS DEL_LF_ROWS
-------- -------- -------- -------- -------- -------- -----------
2 57 1 64 89 9949 0

• Situation après une forte activité de mises à jour (uniquement UPDATE) sur la table

SQL> SELECT height,lf_blks,br_blks,blocks,pct_used,


2 lf_rows,del_lf_rows
3 FROM index_stats WHERE name=’ADHERENT$IX01’;
HEIGHT LF_BLKS BR_BLKS BLOCKS PCT_USED LF_ROWS DEL_LF_ROWS
-------- -------- -------- -------- -------- -------- -----------
2 115 1 128 70 13177 3228

Dans cet exemple, nous voyons que des blocs supplémentaires ont été alloués à l’index et
ont été utilisés, mais avec une dégradation du taux d’occupation. La colonne
DEL_LF_ROWS montre que des entrées ont été supprimées, alors qu’il n’y a eu aucune
suppression dans la table ; mais, comme nous l’avions indiqué précédemment, une
modification de clé d’index se traduit par une suppression (d’où les DEL_LF_ROWS) puis
une insertion (d’où l’utilisation éventuelle de nouveaux blocs).

c. Problèmes possibles sur le stockage

Les problèmes possibles sur le stockage d’un index sont les suivants :

• espace inutilisé alloué à l’index ;


• faible taux d’occupation moyen des blocs et/ou profondeur importante de l’arbre.

Espace inutilisé alloué à un index

Il y a de l’espace inutilisé alloué à un index si le nombre de blocs occupés est faible par
rapport au nombre de blocs alloués, et si l’index ne va plus grossir (ou peu).

Le nombre de blocs occupés est donné par la somme de la valeur des colonnes LF_BLKS et
BR_BLKS de la vue INDEX_STATS et le nombre de blocs alloués par la valeur de la colonne
BLOCKS de la vue INDEX_STATS.

Exemple :

SQL> SELECT lf_blks+br_blks "occupés",blocks "alloués"


2 FROM index_stats WHERE name=’ADHERENT$IX01’;

41 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

occupés alloués
-------- --------
116 128

Ce premier problème n’a pas d’incidence sur les performances (les blocs au-delà de la
HWM ne sont jamais lus) ; il conduit juste à un gaspillage d’espace disque.

Faible taux d’occupation moyen des blocs et/ou profondeur importante de l’index

Le stockage interne d’un index peut être considéré comme dégradé si une ou plusieurs des
conditions suivantes sont vérifiées :

• Le rapport DEL_LF_ROWS/LF_ROWS est élevé (supérieur à 10 % ou 20 %).


• Le pourcentage d’occupation (PCT_USED) est faible (inférieur à 70 %).
• La profondeur de l’arbre d’index (HEIGHT) est élevée (strictement supérieure à 5).

Un mauvais remplissage des blocs peut être lié à une valeur inadaptée de PCTFREE lors de
la création de l’index et/ou à un index très volatile (nombreuses mises à jour). Ce
deuxième problème a des incidences sur les performances et sur l’utilisation de l’espace
dans le Database Buffer Cache. Moins les blocs sont pleins, plus l’index est volumineux et
profond, ce qui augmente le nombre d’entrées/sorties pour le parcours de l’arbre.

Un index créé sur une table très volumineuse peut avoir un arbre profond. Ce qu’il faut
donc surveiller, c’est davantage la dégradation au fil du temps (surtout si la volumétrie de
la table reste par ailleurs, stable) qu’une situation à un instant donné.

Exemple :

• Avant

SQL SELECT height,pct_used,ROUND(del_lf_rows/lf_rows*100) PCT_DEL


2 FROM index_stats WHERE name=’ADHERENT$IX01’;
HEIGHT PCT_USED PCT_DEL
-------- -------- --------
2 89 0

• Après

SQL> SELECT height,pct_used,ROUND(del_lf_rows/lf_rows*100) PCT_DEL


2 FROM index_stats WHERE name=’ADHERENT$IX01’;
HEIGHT PCT_USED PCT_DEL
-------- -------- --------
2 70 24

Sur cet exemple, le stockage de l’index s’est dégradé au fil du temps (alors que la
volumétrie de la table n’a pratiquement pas changé).

8. Réorganiser le stockage d’un index


a. Vue d’ensemble

Les besoins de réorganisation d’un index sont variés :

• libérer de l’espace libre au-dessus de la HWM ;

42 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

• réorganiser un index dont la structure s’est dégradée ;


• réorganiser plus globalement le stockage de l’index : changement de tablespace,
réduction du nombre d’extensions, changement de PCTFREE, etc.

Libérer de l’espace situé au-dessus de la HWM permet de récupérer de l’espace alloué à


l’index mais jamais utilisé (et estimé jamais utilisable). Améliorer le taux de remplissage
des blocs permet aussi éventuellement de libérer de l’espace inutilisé (l’espace libre des
blocs) situé cette fois, en dessous de la HWM.

Plusieurs techniques sont à notre disposition pour réorganiser le stockage d’un index :

• Ordre SQL ALTER INDEX ... DEALLOCATE UNUSED ;


• Ordre SQL ALTER INDEX ... COALESCE ;
• Ordre SQL ALTER INDEX ... SHRINK SPACE ;
• Ordre SQL ALTER INDEX ... REBUILD.

Il est évidemment aussi possible de supprimer l’index (ordre SQL DROP INDEX) puis de le
créer de nouveau (ordre SQL CREATE INDEX), mais une reconstruction (ordre SQL ALTER
INDEX ... REBUILD) se révèle généralement plus intéressante.

Le tableau suivant résume les techniques envisageables (√) et celles qui sont les mieux
adaptées (☺) à tel ou tel besoin :

DEALLOCATE COALESCE SHRINK REBUILD


Libérer de l’espace au-dessus de la HWM ☺ √ √
Améliorer le taux de remplissage des
☺ ☺ ☺
blocs
Réorganiser plus globalement ☺

Réorganiser le stockage d’un index est moins compliqué que réorganiser le stockage d’une
table car les données ne sont pas affectées et la table est toujours accessible et
pleinement opérationnelle.

Lors d’un traitement massif sur une table (chargement, purge), il peut être intéressant de
supprimer tout ou partie des index de la table avant le traitement et de les recréer ensuite. La
performance globale est meilleure et l’index est neuf (non dégradé) à l’arrivée.

b. L’ordre SQL ALTER INDEX ... DEALLOCATE UNUSED

L’ordre SQL ALTER INDEX ... DEALLOCATE UNUSED permet de libérer l’espace d’un index
situé au-dessus de la HWM.

Syntaxe

ALTER INDEX nom_index DEALLOCATE UNUSED [ KEEP valeur [K|M] ] ;

Exemple :

ALTER INDEX adherent$pk DEALLOCATE UNUSED;

43 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

ALTER INDEX adherent$pk DEALLOCATE UNUSED KEEP 0;


ALTER INDEX adherent$pk DEALLOCATE UNUSED KEEP 1M;

Le fonctionnement est le même que pour une table (Gestion des tables). N’oubliez pas que
l’espace initialement alloué est par défaut préservé ; il faut utiliser la clause KEEP pour
libérer de l’espace à l’intérieur de l’espace initialement alloué à l’index.

c. L’ordre SQL ALTER INDEX ... COALESCE

L’ordre SQL ALTER INDEX ... COALESCE permet de fusionner le contenu de blocs feuilles
adjacents qui contiennent de l’espace libre. Grosso modo, deux blocs feuilles adjacents
qui ont 50 % d’espace libre peuvent être fusionnés en un seul bloc, ce qui libère un bloc.

Syntaxe

ALTER INDEX nom_index COALESCE ;

L’ordre SQL ALTER INDEX ... COALESCE n’effectue, par contre, aucune opération sur les
blocs branches ; la profondeur de l’arbre ne change pas. Cette opération est relativement
rapide et ne nécessite pas d’espace de stockage supplémentaire.

Exemple :

• Situation de départ

SQL> SELECT height,lf_blks,br_blks,blocks,pct_used,


2 lf_rows,del_lf_rows
3 FROM index_stats WHERE name=’ADHERENT$IX01’;
HEIGHT LF_BLKS BR_BLKS BLOCKS PCT_USED LF_ROWS DEL_LF_ROWS
-------- -------- -------- -------- -------- -------- -----------
2 257 1 384 90 64000 0

• Situation après des modifications importantes dans la table : l’index est dégradé (la
profondeur a changé)

SQL> SELECT height,lf_blks,br_blks,blocks,pct_used,


2 lf_rows,del_lf_rows
3 FROM index_stats WHERE name=’ADHERENT$IX01’;
HEIGHT LF_BLKS BR_BLKS BLOCKS PCT_USED LF_ROWS DEL_LF_ROWS
-------- -------- -------- -------- -------- -------- -----------
3 580 3 640 78 83580 33785

• Opération de COALESCE

SQL> ALTER INDEX diane.adherent$ix01 COALESCE;

• Situation à l’arrivée (après ANALYZE INDEX ... VALIDATE STRUCTURE)

SQL> SELECT height,lf_blks,br_blks,blocks,pct_used,


2 lf_rows,del_lf_rows
3 FROM index_stats WHERE name=’ADHERENT$IX01’;
HEIGHT LF_BLKS BR_BLKS BLOCKS PCT_USED LF_ROWS DEL_LF_ROWS
-------- -------- -------- -------- -------- -------- -----------
3 370 3 640 88 49838 43

44 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

L’opération de COALESCE a permis de réduire le nombre de blocs utilisés, et de retrouver


un pourcentage d’occupation satisfaisant et un faible taux de lignes supprimées (il en
reste quelques-unes). Par contre, la profondeur de l’arbre n’a pas changé.

Dans de nombreuses situations, cette simple opération de COALESCE est suffisante pour
retrouver un index performant.

d. L’ordre SQL ALTER INDEX ... SHRINK SPACE

L’ordre SQL ALTER INDEX ... SHRINK SPACE est analogue à l’ordre SQL ALTER TABLE ...
SHRINK SPACE : il permet de compacter les lignes d’un index, mais uniquement pour un
index stocké dans un tablespace géré localement avec une gestion automatique de
l’espace dans les segments. Par défaut, Oracle compacte aussi le segment, ajuste la HWM
et libère l’espace ainsi récupéré.

Syntaxe

ALTER INDEX nom_index SHRINK SPACE [COMPACT] ;

Avec l’option COMPACT, Oracle se contente de compacter les lignes, mais sans ajuster la
HWM ni libérer d’espace. L’exécution ultérieure d’un autre ordre SQL ALTER TABLE ...
SHRINK SPACE permettra de terminer l’opération.

L’ordre SQL ALTER INDEX ... SHRINK SPACE COMPACT est équivalent à l’ordre SQL ALTER
INDEX ... COALESCE.

Exemple

• Situation après des modifications importantes dans la table : l’index est dégradé.

SQL> SELECT height,lf_blks,br_blks,blocks,pct_used,


2 lf_rows,del_lf_rows
3 FROM index_stats WHERE name=’ADHERENT$IX01’;
HEIGHT LF_BLKS BR_BLKS BLOCKS PCT_USED LF_ROWS DEL_LF_ROWS
-------- -------- -------- -------- -------- -------- -----------
3 580 3 640 78 83580 33785

• Opération de SHRINK SPACE

SQL> ALTER INDEX diane.adherent$ix01 SHRINK SPACE;

• Situation à l’arrivée (après ANALYZE INDEX ... VALIDATE STRUCTURE)

SQL> SELECT height,lf_blks,br_blks,blocks,pct_used,


2 lf_rows,del_lf_rows
3 FROM index_stats WHERE name=’ADHERENT$IX01’;
HEIGHT LF_BLKS BR_BLKS BLOCKS PCT_USED LF_ROWS DEL_LF_ROWS
-------- -------- -------- -------- -------- -------- -----------
3 374 3 400 87 49800 0

À quelques blocs près, l’opération de SHRINK SPACE donne le même résultat que
l’opération de COALESCE, sauf sur les blocs utilisés (400 contre 640) ; l’espace a été
libéré.

45 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

L’opération de COALESCE est légèrement plus rapide que l’opération de SHRINK SPACE.

e. L’ordre SQL ALTER INDEX ... REBUILD

L’ordre SQL ALTER INDEX ... REBUILD permet de reconstruire en totalité un index (blocs
branches et blocs feuilles) et donc, de réorganiser son stockage.

Syntaxe

ALTER INDEX nom_index REBUILD


[ TABLESPACE nom_tablespace ]
[ PCTFREE valeur ]
[ clause_stockage ]
[ ONLINE ]
[ NOCOMPRESS | COMPRESS [n] ]
[ LOGGING | NOLOGGING ] ;
- clause_stockage
STORAGE ( [ INITIAL valeur [K|M] ]
[ NEXT valeur [K|M] ]
[ MINEXTENTS valeur ]
[ MAXEXTENTS { valeur | UNLIMITED } ]
[ PCTINCREASE valeur ] )

Exemple :

ALTER INDEX adherent$pk REBUILD


PCTFREE 40
STORAGE ( INITIAL 10M ) ;

Les options sont les mêmes que celles de l’ordre SQL CREATE INDEX.

Sans option, l’ordre SQL ALTER INDEX ... REBUILD reconstruit l’index avec les mêmes
clauses de stockage. Cette syntaxe peut être utilisée pour reconstruire un index dont les
clauses de stockage sont bonnes mais qui s’est dégradé au fil du temps, du fait d’une forte
activité de mise à jour.

L’ordre SQL ALTER INDEX ... REBUILD est plus intéressant que la recréation
(DROP+CREATE) pour deux raisons :

• L’index est reconstruit à partir de l’index existant : aucun tri n’est nécessaire.
• L’ancien index est toujours disponible : les requêtes peuvent l’utiliser.

Les performances sont donc globalement améliorées pour tout le monde.

Ces deux avantages disparaissent si l’index d’origine est UNUSABLE(suite à l’exécution


d’un ordre SQL ALTER TABLE ... MOVE par exemple).

L’inconvénient majeur par rapport à une recréation est qu’il faut de l’espace disponible
pour faire cohabiter temporairement l’ancien index et le nouveau.

Exemple 1

• Situation après des modifications importantes dans la table : l’index est dégradé

46 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

SQL> SELECT height,lf_blks,br_blks,blocks,pct_used,


2 lf_rows,del_lf_rows
3 FROM index_stats WHERE name=’ADHERENT$IX01’;
HEIGHT LF_BLKS BR_BLKS BLOCKS PCT_USED LF_ROWS DEL_LF_ROWS
-------- -------- -------- -------- -------- -------- -----------
3 580 3 640 78 83580 33785

• Opération de REBUILD

SQL> ALTER INDEX diane.adherent$ix01 REBUILD;


Index modifié.

• Situation à l’arrivée (après ANALYZE INDEX ... VALIDATE STRUCTURE)

SQL> SELECT height,lf_blks,br_blks,blocks,pct_used,


2 lf_rows,del_lf_rows
3 FROM index_stats WHERE name=’ADHERENT$IX01’;
HEIGHT LF_BLKS BR_BLKS BLOCKS PCT_USED LF_ROWS DEL_LF_ROWS
-------- -------- -------- -------- -------- -------- -----------
2 364 1 384 89 49805 0

L’index a été complètement reconstruit : il a retrouvé une profondeur de 2 et utilise un


peu moins de blocs.

Exemple 2

• Situation de départ : index non compressé

SQL> SELECT lf_blks,br_blks,blocks,opt_cmpr_count,opt_cmpr_pctsave


2 FROM index_stats WHERE name=’ADHERENT$IX01’;
LF_BLKS BR_BLKS BLOCKS OPT_CMPR_COUNT OPT_CMPR_PCTSAVE
-------- -------- -------- -------------- ----------------
58 1 72 2 28

• Compression sur les deux premières colonnes

SQL> ALTER INDEX diane.adherent$ix01 REBUILD COMPRESS 2;

• Situation à l’arrivée (après ANALYZE INDEX ... VALIDATE STRUCTURE)

SQL> SELECT lf_blks,br_blks,blocks,opt_cmpr_count,opt_cmpr_pctsave


2 FROM index_stats WHERE name=’ADHERENT$IX01’;
LF_BLKS BR_BLKS BLOCKS OPT_CMPR_COUNT OPT_CMPR_PCTSAVE
-------- -------- -------- -------------- ----------------
41 1 48 2 0

L’index a été reconstruit avec une compression sur les deux premières colonnes. Le gain
annoncé était de 28 % ; il est de 28,8 %.

f. Conclusion

Si le fait que le REBUILD nécessite temporairement de l’espace ne vous pose pas de


problème, utilisez en priorité cette technique pour réorganiser le stockage d’un
index : vous obtiendrez le meilleur résultat.

47 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Par contre, si vous avez des problèmes de place, vous pouvez employer le COALESCE pour
un résultat généralement très satisfaisant, mais vous ne libérez pas d’espace pour d’autres
segments. Dans ce cas, le SHRINK SPACE peut être envisagé ; il présente l’avantage de
libérer l’espace récupéré.

9. Surveiller l’utilisation d’un index

Depuis Oracle9i, il est possible de surveiller les index afin de déterminer s’ils sont utilisés
ou non. Un index non utilisé peut être supprimé pour libérer de l’espace et améliorer les
performances des mises à jour.

L’ordre SQL ALTER INDEX permet d’activer ou de désactiver la surveillance d’un index :

ALTER INDEX nom_index MONITORING USAGE | NOMONITORING USAGE ;

Exemple :

ALTER INDEX adherent$ix01 MONITORING USAGE ;

La clause MONITORING USAGE peut aussi être utilisée dans l’ordre SQL CREATE INDEX pour
activer la surveillance dès la création de l’index (NOMONITORING par défaut).

La vue V$OBJECT_USAGE sera ensuite interrogée pour déterminer si un index a été utilisé
pendant qu’il était sous surveillance :

INDEX_NAME : Nom de l’index.

TABLE_NAME : Nom de la table sur laquelle l’index est créé.

MONITORING : Indique si l’index est actuellement sous surveillance (YES ou NO).

USED : Indique si l’index a été utilisé au moins une fois pendant sa surveillance (YES ou
NO).

START_MONITORING : Date/heure du début de la surveillance de l’index.

END_MONITORING : Date/heure de la fin de la surveillance de l’index (vide si la


surveillance est en cours).

La vue V$OBJECT_USAGE doit être interrogée sous le compte du propriétaire de l’index.

Exemple :

SQL> SELECT * FROM v$object_usage


2 WHERE index_name = ’ADHERENT$IX01’ ;

INDEX_NAME TABLE_NAME MONITORING USED


--------------- --------------- ---------- ----
START_MONITORING END_MONITORING
------------------- -------------------
ADHERENT$IX01 ADHERENT YES YES

48 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

01/04/2005 10:37:40

Dans cet exemple, l’index ADHERENT$IX01 créé sur la table ADHERENT a été utilisé au
moins une fois depuis que l’index est sous surveillance ; l’index est toujours sous
surveillance (la colonne END_MONITORING est vide).

10. Trouver des informations sur les index

Plusieurs vues du dictionnaire de données permettent d’obtenir des informations sur les
index :

• DBA_INDEXES : informations sur les index ;


• DBA_IND_COLUMNS : informations sur les colonnes des index ;
• INDEX_STATS : résultat du dernier ANALYZE INDEX ... VALIDATE STRUCTURE ;
• DBA_SEGMENTS : informations sur les segments (dont ceux de type index) ;
• DBA_EXTENTS : informations sur les extensions allouées aux segments (dont ceux de
type index)

Les vues DBA_SEGMENTS et DBA_EXTENTS ont été présentées à la section Trouver des
informations sur les tablespaces et les fichiers de données du chapitre Gestion des
tablespaces et des fichiers de données.

La vue INDEX_STATS a été présentée à la section Gestion des index B-tree. L’ordre SQL
ANALYZE INDEX ... VALIDATE STRUCTURE.

Les colonnes intéressantes des différentes autres vues sont présentées ci-après.

DBA_INDEXES

INDEX_NAME : Nom de l’index.

OWNER : Nom du propriétaire de l’index.

TABLE_NAME : Nom de la table sur laquelle l’index est créé.

TABLE_OWNER : Nom du propriétaire de la table.

UNIQUENESS : Nature de l’index (UNIQUE ou NONUNIQUE).

TABLESPACE_NAME : Nom du tablespace dans lequel l’index est stocké.

PCT_FREE : Valeur du PCTFREE.

COMPRESSION : Indique si la compression de l’index est active (ENABLED ou DISABLED).

PREFIX_LENGTH : Nombre de colonnes dans le préfixe de la compression.

LOGGING : Indique si le mode LOGGING est actif ou non pour l’index (YES ou NO).

STATUS : Statut de l’index (VALID ou UNUSABLE).

49 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

BLEVEL * : Profondeur de l’arbre au niveau des branches (ne tient pas compte des
feuilles). 0 si le bloc racine est égal au bloc feuille.

LEAF_BLOCKS * : Nombre de blocs feuilles dans l’index.

NUM_ROWS * : Nombre de lignes dans l’index.

CLUSTERING_FACTOR * : Facteur de regroupement des données dans la table.

AVG_LEAF_BLOCKS_PER_KEY * : Nombre moyen de blocs feuilles par valeur de la clé.

AVG_DATA_BLOCKS_PER_KEY * : Nombre moyen de blocs de données (table) par valeur de


la clé.

DISTINCT_KEYS * : Nombre de valeurs distinctes dans l’index.

SAMPLE_SIZE * : Taille de l’échantillon utilisé lors du calcul des statistiques.

LAST_ANALYZED * : Date et heure de la dernière analyse réalisée sur l’index.

* Statistiques sur l’index, calculées par défaut lorsque les statistiques sont générées sur la
table. Ces dernières sont utilisées par l’optimiseur.

DBA_IND_COLUMNS

INDEX_NAME : Nom de l’index.

OWNER : Nom du propriétaire de l’index.

TABLE_NAME : Nom de la table sur laquelle l’index est créé.

TABLE_OWNER : Nom du propriétaire de la table.

COLUMN_NAME : Nom de la colonne utilisée dans la clé de l’index.

COLUMN_POSITION : Position de la colonne dans la clé de l’index.

Les statistiques et l’optimiseur Oracle


L’optimiseur Oracle est chargé de déterminer le plan d’exécution des requêtes, c’est-à-
dire la manière dont Oracle va exécuter la requête.

Depuis maintenant plusieurs versions, Oracle recommande de faire fonctionner


l’optimiseur dans le mode CBO (Cost Based Optimizer - Optimiseur basé sur les coûts).
Depuis la version 10, seul le mode CBO est supporté ; le mode RBO (Rule Based Optimizer -
Optimiseur basé sur les règles) n’est plus supporté.

Pour fonctionner, l’optimiseur dans le mode CBO a besoin de statistiques sur les tables, les
colonnes et les index. Ces statistiques sont calculées avec le package DBMS_STATS.

50 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Dans les versions précédentes, il était de la responsabilité du DBA de programmer une


tâche périodique de collecte des statistiques, afin que l’optimiseur ne travaille pas avec
des données obsolètes.

Depuis la version 10, les statistiques sont automatiquement collectées par Oracle. En
version 11, cette collecte s’effectue par l’intermédiaire d’une tâche de maintenance
automatisée (cf. Oracle Enterprise Manager Database Control du chapitre Les Outils
d’administration).

Par défaut, cette tâche de maintenance collecte les statistiques sur les objets de la base
de données qui n’ont pas de statistiques ou qui ont des statistiques jugées obsolètes (si
plus de 10% des lignes de l’objet sous-jacent ont été modifiées) ; la procédure traite en
priorité les objets qui en ont le plus besoin. Les paramètres de cette tâche automatique
peuvent être configurées dans le Database Control (cf. Oracle Enterprise Manager
Database Control du chapitre Les Outils d’administration).

Vous pouvez collecter les statistiques en exécutant manuellement certaines procédures du


package DBMS_STATS :

• GATHER_TABLE_STATS(owname,tabname) : statistiques sur une table (et par défaut


sur les colonnes et index de la table) ;
• GATHER_INDEX_STATS(owname,indname) : statistiques sur un index ;
• GATHER_SCHEMA_STATS(owname) : statistiques sur toutes les tables et index d’un
schéma.

Les paramètres sont les suivants :

Ownname : Nom du schéma (NULL pour le schéma courant).

Tabname : Nom de la table.

Indname : Nom de l’index.

Ces procédures ont d’autres paramètres dont les valeurs par défaut sont a priori
satisfaisantes (au moins dans un premier temps).

Les statistiques peuvent êtres consultées dans les vuesDBA_TABLES, DBA_TAB_ COLUMNSet
DBA_INDEXES.

Exemple :

SQL> EXEC dbms_stats.gather_schema_stats(’DIANE’)


Procédure PL/SQL terminée avec succès.

SQL> SELECT num_rows,blocks,sample_size,last_analyzed


2 FROM dba_tables WHERE table_name=’ADHERENT’ AND owner=’DIANE’;
NUM_ROWS BLOCKS SAMPLE_SIZE LAST_ANA
---------- ---------- ----------- --------
9964 137 9964 20/07/08

Le Database Control permet de gérer les statistiques de l’optimiseur. Pour accéder à la


page de gestion des statistiques de l’optimiseur, cliquez sur le lien Serveur sur la page

51 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

d’accueil puis sur le lien Gérer les statistiques de l’optimiseur (cadre Optimiseur
d’interrogation).

Utiliser le Database Control


1. Les tables

Dans le Database Control, cliquez sur le lien Schéma sur la page d’accueil puis sur le lien
Tables (cadre Objets de base de données) pour accéder à la page de gestion des tables.

La section Rechercher permet de rechercher des objets selon leur type, leur schéma ou
leur nom.

À partir de cette page, vous pouvez effectuer diverses actions sur les tables :

• créer une nouvelle table (bouton Créer ou menu Créer comme ) ;


• supprimer une table (bouton Supprimer avec des options) ;

52 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

• modifier une table (bouton Modifier) ;


• créer un index sur une table (menu Créer un index) ;
• extraire la définition d’une table (menu Générer du code DDL) ;
• collecter les statistiques sur une table (menu Gérer les statistiques de
l’optimiseur) ;
• réorganiser une table (menu Réorganiser) ;
• exécuter le conseiller sur les segments (menu Exécuter la fonction de conseil sur les
segments) ;
• compacter (SHRINK) la table (menu Réduire le segment).

En cliquant sur le lien du nom de table, ou en cliquant sur les boutons Créer, Modifier ou
Visualiser, vous arrivez sur la page de définition d’une table :

Cette page propose plusieurs onglets (sous forme de liens) permettant de gérer les
différentes caractéristiques de la table.

L’onglet Segments permet de voir l’espace utilisé par la table et ces index :

53 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Le graphique donne la tendance d’utilisation de l’espace pour le segment sélectionné dans


la liste et la période indiquées. Il peut être utilisé pour estimer la volumétrie d’une table
ou d’un index à une échéance donnée.

2. Les index

Dans le Database Control, cliquez sur le lien Schéma sur la page d’accueil puis sur le lien
Index (cadre Objet de base de données) pour accéder à la page de gestion des index.

54 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

La section Rechercher permet de rechercher des objets selon leur type, leur schéma ou
leur nom.

À partir de cette page, vous pouvez effectuer diverses actions sur les index :

• créer un nouvel index (bouton Créer ou menu Créer comme) ;


• supprimer un index (bouton Supprimer) ;
• modifier un index (bouton Modifier) ;
• extraire la définition d’un index (menu Générer du code DDL) ;
• collecter les statistiques sur l’index (menu Gérer les statistiques de l’optimiseur) ;
• réorganiser un index (menu Réorganiser) ;
• exécuter le conseiller sur les segments (menu Exécuter la fonction de conseil sur les
segments) ;
• compacter (SHRINK) un index (menu Réduire le segment).

En cliquant sur le lien du nom d’index, ou en cliquant sur les boutons Créer, Modifier ou
Visualiser, vous arrivez sur la page de définition d’un index :

55 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Cette page propose plusieurs onglets (sous forme de liens) permettant de gérer les
différentes caractéristiques de l’index. L’onglet Segments permet de voir l’espace utilisé
par l’index (comme pour une table).

3. Réorganiser une table ou un index

Le menu Réorganiser disponible sur les tables, les index et les tablespace permet
d’exécuter un assistant de réorganisation du stockage des objets. Cet assistant peut aussi
être appelé en cliquant sur le lien Réorganiser les objets dans le cadre Objets de base de
données de l’onglet Schéma.

Les principales étapes de l’assistant sont les suivantes :

Définir la liste des objets à réorganiser

Sur cette page, vous pouvez définir la liste des objets à réorganiser en cliquant sur les
boutons Ajouter et Enlever. Les boutons Définir les attributs et Définir les attributs par
type permettent de spécifier les caractéristiques de stockage : nouveau tablespace, taille
initiale, PCTFREE, etc.

Définir les caractéristiques de la réorganisation

Cette page permet notamment d’indiquer si la réorganisation doit s’effectuer en ligne ou


hors ligne. La réorganisation en ligne privilégie la disponibilité de l’objet au détriment de
la vitesse ; c’est l’inverse pour la réorganisation hors ligne.

Rapport d’impact

Cette page donne des informations sur les problèmes potentiels qui peuvent survenir au
cours de la réorganisation (manque d’espace par exemple) ; si c’est le cas, il faut réaliser
les modifications nécessaires avant de lancer l’opération.

Programmation

Cette page permet de nommer le travail, de fournir les informations d’identification et de


connexion, et de programmer l’exécution du travail (maintenant ou ultérieurement).

Récapitulatif

56 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Cette page donne un récapitulatif du travail qui va être effectué. En cliquant sur le bouton
radio Script complet, vous pouvez consulter (et récupérer) le script complet de la
réorganisation. Cliquez sur le bouton Soumettre un travail pour lancer l’opération.

Cet assistant utilise une des techniques suivantes :

• réorganisation d’un index : ordre SQL ALTER INDEX ... REBUILD ;


• réorganisation d’une table hors ligne : ordre SQL ALTER TABLE ... MOVE ;
• réorganisation d’une table en ligne : package DBMS_REDEFINITION.

Le résultat du travail peut être consulté en cliquant sur le lien Travaux de la page
d’accueil (cadre Liens associés en bas).

4. Le conseiller sur les segments

Le Database Control dispose d’un conseiller sur les segments (Segment Advisor). Ce
conseiller donne des recommandations sur l’opportunité ou non de compacter (SHRINK) un
segment.

Cet assistant peut être appelé en utilisant le menu Exécuter la fonction de conseil sur les
segments disponible sur les tables, les index et les tablespace ou en cliquant sur le lien
Fonction de conseil sur les segments sur la page Centre de conseil (accessible par le lien
Centre de conseil à partir de la page d’accueil).

Par défaut, cet assistant est aussi programmé pour s’exécuter en tâche de maintenance
automatisée (cf. Oracle Enterprise Manager Database Control du chapitre Les Outils
d’administration). Vous serez donc rarement amené à lancer le conseiller manuellement.

Sur la page d’accueil du Database Control, dans le cadre Récapitulatif de l’espace, pour
pouvez voir rapidement s’il y a des recommandations sur les segments :

57 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

En cliquant sur le lien associé, vous pouvez afficher la liste des recommandations :

Si vous cliquez sur le bouton Détails des recommandations, vous pouvez consulter le détail
de la recommandation sélectionnée :

Pour implémenter les recommandations, il vous suffit de sélectionner une ou plusieurs


tâches dans la liste et de cliquer sur le bouton Implémenter, ou de cliquer directement sur
le bouton Réduire d’une tâche. Le Database Control affiche alors la page suivante :

58 | P a g e  
 
Support de Cours ORACLE 11g : Administration, par Mawunya Koffi GBENOU 
 

Cette page vous permet de choisir une option de réduction (SHRINK SPACE ou SHRINK
SPACE COMPACT) et de soumettre le travail (bouton Implémenter). Le résultat du travail
peut être consulté en cliquant sur le lien Travaux de la page Serveur (cadre Oracle
Scheduler).

D’une manière plus générale, les résultats des différents conseillers sont visibles lorsque
vous affichez la page Centre de conseil :

En cliquant sur le lien correspondant à une tâche, vous pouvez visualiser les
recommandations du conseiller.

59 | P a g e  
 

Vous aimerez peut-être aussi