Sie sind auf Seite 1von 267

Proprit de Albiri Sigue <tag.tog@gmail.

com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011

























R

r
e
n
c
e




Rseaux
et tlcom
Scurit
Systme
dexploitation




bases de
donnes
Optimisation des


Mise en uvre sous Oracle




























Laurent Navarro
Programmation
Dveloppement
web

Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Optimisation des
bases de donnes
Mise en uvre sous Oracle
Laurent Navarro
Avec la contribution technique
dEmmanuel Lecoester
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Pearson Education France a apport le plus grand soin la ralisation de ce livre afn de
vous fournir une information complte et fable. Cependant, Pearson Education France
nassume de responsabilits, ni pour son utilisation, ni pour les contrefaons de brevets
ou atteintes aux droits de tierces personnes qui pourraient rsulter de cette utilisation.
Les exemples ou les programmes prsents dans cet ouvrage sont fournis pour
illustrer les descriptions thoriques. Ils ne sont en aucun cas destins une utilisation
commerciale ou professionnelle.
Pearson Education France ne pourra en aucun cas tre tenu pour responsable des
prjudices oudommages de quelque nature que ce soit pouvant rsulter de lutilisation
de ces exemples ou programmes.
Tous les noms de produits ou marques cits dans ce livre sont des marques dposes par
leurs propritaires respectifs.
Publi par Pearson Education France
47 bis, rue des Vinaigriers
75010 PARIS
Tl. : 01 72 74 90 00
www.pearson.fr
Mise en pages : TyPAO
ISBN : 978-2-7440-4156-3
Copyright 2010 Pearson Education France
Tous droits rservs
Aucune reprsentation ou reproduction, mme partielle, autre que celles prvues larticle L. 122-5 2 et 3 a)
du code de la proprit intellectuelle ne peut tre faite sans lautorisation expresse de Pearson Education France
ou, le cas chant, sans le respect des modalits prvues larticle L. 122-10 dudit code.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Table des matires
Prface ............................................................................................................................................... IX
propos de lauteur ...................................................................................................................... XI
Introduction ..................................................................................................................................... 1
1 Introduction aux SGBDR ................................................................................................... 5
1.1 Quest-ce quune base de donnes? .................................................................... 5
1.1.1 Systme de gestion des bases de donnes ...................................... 6
1.2 Modle de stockage des donnes ......................................................................... 7
1.2.1 Organisation des donnes .................................................................. 7
1.2.2 Le RowID ............................................................................................... 10
1.2.3 Online Redo Log et Archived Redo Log ........................................ 10
1.2.4 Organisation des tables ........................................................................ 11
1.2.5 Row Migration et Row Chaining ...................................................... 12
1.2.6 Le cache mmoire ................................................................................ 13
1.3 Intrt des index dans les SGBDR ....................................................................... 14
1.4 Analyse du comportement du SGBDR ............................................................... 15
1.4.1 Excution dune requte SQL ............................................................ 15
1.4.2 Optimiseur CBO (Cost Based Optimizer) ...................................... 16
Axe 1
tude et optimisation dumodle de donnes
2 Modle relationnel ................................................................................................................ 21
2.1 Prsentation .............................................................................................................. 21
2.2 Les bons rfexes sur le typage des donnes ...................................................... 25
2.2.1 Les types sous Oracle .......................................................................... 28
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
IV Optimisation des bases de donnes
2.2.2 Les types sous SQL Server ................................................................. 30
2.2.3 Les types sous MySQL........................................................................ 31
3 Normalisation, base du modle relationnel ................................................................... 33
3.1 Normalisation .......................................................................................................... 33
3.1.1 Premire forme normale (1NF) ......................................................... 34
3.1.2 Deuxime forme normale (2NF) ....................................................... 35
3.1.3 Troisime forme normale (3NF) ....................................................... 36
3.1.4 Forme normale de Boyce Codd (BCNF) ........................................ 37
3.1.5 Autres formes normales ...................................................................... 38
3.2 Dnormalisation et ses cas de mise en uvre .................................................... 38
3.2.1 La dnormalisation pour historisation ............................................. 38
3.2.2 La dnormalisation pour performance et simplifcation
en environnement OLTP ..................................................................... 40
3.2.3 La dnormalisation pour performance
en environnement OLAP .................................................................... 42
3.3 Notre base de test .................................................................................................... 43
Axe 2
tude et optimisation desrequtes
4 Mthodes et outils de diagnostic ....................................................................................... 49
4.1 Approche pour optimiser ....................................................................................... 49
4.1.1 Mesurer .................................................................................................... 50
4.1.2 Comprendre le plan dexcution ....................................................... 55
4.1.3 Identifer les requtes qui posent des problmes ........................... 61
4.2 Outils complmentaires ......................................................................................... 64
4.2.1 Compteurs de performance Windows .............................................. 64
4.2.2 SQL Tuning Advisor (Oracle) ........................................................... 65
4.2.3 SQL Access Advisor (Oracle) ............................................................ 66
4.2.4 SQL Trace (Oracle) ............................................................................... 67
4.2.5 Outils SQL Server................................................................................. 72
4.2.6 Outils MySQL ....................................................................................... 73
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Table des matires V
5 Techniques doptimisation standard au niveau base de donnes ............................ 77
5.1 Statistiques sur les donnes ................................................................................... 77
5.1.1 Ancienne mthode de collecte ........................................................... 78
5.1.2 Nouvelle mthode de collecte ............................................................ 78
5.1.3 Slectivit, cardinalit, densit .......................................................... 80
5.2 Utilisation des index ............................................................................................... 85
5.2.1 Index B*Tree .......................................................................................... 86
5.2.2 Index sur fonction ................................................................................. 99
5.2.3 Reverse Index ......................................................................................... 100
5.2.4 Index bitmap........................................................................................... 101
5.2.5 Bitmap Join Index ................................................................................. 108
5.2.6 Full Text Index ....................................................................................... 111
5.3 Travail autour des tables ........................................................................................ 118
5.3.1 Paramtres de table ............................................................................... 118
5.3.2 Index Organized Table ........................................................................ 122
5.3.3 Cluster ...................................................................................................... 132
5.3.4 Partitionnement des donnes .............................................................. 135
5.3.5 Les vues matrialises ......................................................................... 146
5.3.6 Reconstruction des index et des tables ............................................ 148
6 Techniques doptimisation standard des requtes ....................................................... 153
6.1 Rcriture des requtes .......................................................................................... 153
6.1.1 Transformation de requtes ................................................................ 154
6.1.2 IN versus jointure .................................................................................. 155
6.1.3 Sous-requtes versus anti-jointures .................................................. 156
6.1.4 Exists versus Count .............................................................................. 158
6.1.5 Exists versus IN ..................................................................................... 159
6.1.6 Clause Exists * versus constante ....................................................... 160
6.1.7 Expressions sous requtes .................................................................. 161
6.1.8 Agrgats: Having versus Where ....................................................... 162
6.2 Bonnes et mauvaises pratiques ............................................................................. 163
6.2.1 Mlange des types ................................................................................ 163
6.2.2 Fonctions et expressions sur index ................................................... 163
6.2.3 Impact de loprateur <> sur les index ............................................ 164
6.2.4 Rutilisation de vue .............................................................................. 164
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
VI Optimisation des bases de donnes
6.2.5 Utilisation de tables temporaires ....................................................... 165
6.2.6 Utilisation abusive de SELECT * ...................................................... 165
6.2.7 Suppression des tris inutiles ............................................................... 166
6.2.8 Utilisation raisonne des oprations ensemblistes ....................... 166
6.2.9 Union versus Union ALL ..................................................................... 169
6.2.10 Count(*) versus count(colonne) ........................................................ 170
6.2.11 Rduction du nombre de parcours des donnes ............................ 171
6.2.12 LMD et cls trangres........................................................................ 172
6.2.13 Suppression temporaire des index et des CIR ............................... 173
6.2.14 Truncate versus Delete ........................................................................ 173
6.2.15 Impacts des verrous et des transactions ........................................... 173
6.2.16 Optimisation du COMMIT ................................................................. 175
6.2.17 DBLink et vues ...................................................................................... 176
7 Techniques doptimisation des requtes avances ....................................................... 177
7.1 Utilisation des hints sous Oracle .......................................................................... 177
7.1.1 Syntaxe gnrale ................................................................................... 179
7.1.2 Les hints Optimizer Goal .................................................................... 179
7.1.3 Les hints Access Path ........................................................................... 180
7.1.4 Les hints Query Transformation ....................................................... 181
7.1.5 Les hints de jointure ............................................................................. 182
7.1.6 Autres hints............................................................................................. 183
7.2 Excution parallle ................................................................................................. 183
7.2.1 Les hints de paralllisme ..................................................................... 185
7.3 Utilisation du SQL avanc ..................................................................................... 186
7.3.1 Les Grouping Sets ................................................................................. 186
7.3.2 Rollup Group By.................................................................................... 188
7.3.3 Cube Group By ...................................................................................... 189
7.3.4 Utilisation de WITH ............................................................................. 191
7.3.5 Les fonctions de classement (ranking) ............................................ 192
7.3.6 Autres fonctions analytiques .............................................................. 194
7.3.7 Linstruction MERGE .......................................................................... 195
7.3.8 Optimisation des updates multitables .............................................. 196
7.3.9 Insertion en mode Direct Path ........................................................... 198
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Table des matires VII
7.4 PL/SQL ..................................................................................................................... 198
7.4.1 Impact des triggers ............................................................................... 198
7.4.2 Optimisation des curseurs (BULK COLLECT) ............................. 200
7.4.3 Optimisation du LMD (FORALL) .................................................... 203
7.4.4 SQL dynamique et BULK ................................................................... 208
7.4.5 Traitement des exceptions avec FORALL ....................................... 209
7.4.6 Utilisation de cache de donnes ........................................................ 210
7.4.7 Utilisation du profling ........................................................................ 212
7.4.8 Compilation du code PL/SQL ........................................................... 212
Axe 3
Autres pistes doptimisation
8 Optimisation applicative (hors SQL) ............................................................................. 217
8.1 Impact du rseau sur le modle client/serveur ................................................... 217
8.2 Regroupement de certaines requtes ................................................................... 217
8.3 Utilisation du binding ............................................................................................. 219
8.4 Utilisation de cache local lapplication ............................................................ 221
8.5 Utilisation du SQL procdural .............................................................................. 221
8.6 Gare aux excs de modularit ............................................................................... 221
9 Optimisation de linfrastructure ...................................................................................... 223
9.1 Optimisation de lexcution du SGBDR ............................................................. 223
9.1.1 Ajustement de la mmoire utilisable ................................................ 223
9.1.2 Rpartition des fchiers ........................................................................ 224
9.2 Optimisation matrielle .......................................................................................... 224
9.2.1 Le CPU .................................................................................................... 224
9.2.2 La mmoire vive (RAM) ..................................................................... 225
9.2.3 Le sous-systme disque ....................................................................... 225
9.2.4 Le rseau ................................................................................................. 226
Conclusion ........................................................................................................................................ 227
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
VIII Optimisation des bases de donnes
Annexes
A Gestion interne des enregistrements ................................................................................ 231
A.1 Le RowID ................................................................................................................. 231
A.2 Row Migration et Row Chaining ......................................................................... 232
B Statistiques sur les donnes plus en dtail...................................................................... 235
B.1 Statistiques selon lancienne mthode de collecte ............................................ 235
B.2 Statistiques selon la nouvelle mthode de collecte ........................................... 236
B.3 Histogrammes .......................................................................................................... 240
B.4 Facteur de foisonnement (Clustering Factor) .................................................... 241
C Scripts de cration des tables de test bigemp et bigdept .............................................. 245
D Glossaire .................................................................................................................................. 249
Index ................................................................................................................................................... 251
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Prface
Loptimisation des applications est un sujet bien vaste, souvent objet des dbats
d'experts et gnrateur de quiproquos notamment sur les causes gnrant les effets
constats (lenteur daffchage, fort trafc rseau, saturation du serveur de donnes).
Loptimisation se prsente sous de multiples facettes:
Tantt, elle est purement applicative et touche la mthode de programmation.
Tantt, les drives proviennent dun manque au niveau de la modlisation des
donnes, plus gnralement dun problme d'index ou de paramtrage du serveur
de donnes.
Parfois mme, loptimisation est tout simplement lie une limite de larchitec-
ture physique du systme.
Dans chacun de ces trois cas de fgure majeurs, il est important de mesurer ce
manque doptimisation et de choisir les mtriques les plus discriminantes afn de
pouvoir mesurer les bnfces exacts de loptimisation apporte.
Dans cet ouvrage, Laurent Navarro apporte un lot de rponses concrtes et dtailles
au dveloppeur dapplication, dans une vision rsolument cible sur laccs aux
donnes. Jinsiste bien sur ce point: ce livre nest pas un catalogue des techniques
doptimisation propres chaque serveur de donnes destin aux administrateurs ou
autres experts mais bien un premier pas vers une sensibilisation des dveloppeurs de
tous bords aux contacts avec un serveur de donnes.
Ce livre parcourt les principales techniques doptimisation disponibles pour le dve-
loppeur dapplication: modle de donnes, techniques standard daccs aux donnes
jusqu des techniques trs avances permettant dexploiter au mieux les possibilits
offertes par les principaux diteurs de bases de donnes du march.
Emmanuel Lecoester
Responsable des rubriques SGBD & WinDev
de developpez.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
propos de lauteur
Adolescent, je mamusais avec des bases de donnes DBase II & III, puis jai
dbut ma carrire dans l'industrie avec des bases en fchiers partags Paradox. La
nature des applications a volu, et en 1994 jai commenc travailler sur des bases
Oracle (Version 7). lpoque, cela ncessitait un serveur Unix et un DBA bard
de certifcations. Au fl du temps, les SGBDR client/serveur se sont dmocratises.
Des alternatives au leader sont apparues, contribuant pour une grande part cette
dmocratisation. Cest ainsi quen 2000 jai fait la connaissance de MySQL (3.2
lpoque) pour ma premire application web dveloppe en PHP. Puis jai eu locca-
sion dutiliser dautre bases, telles que SQL Server de Microsoft, Firebird la version
open-source dInterbase ou encore PostgreSQL, autre alternative open-source qui
ne rencontre malheureusement pas le succs quelle mriterait.
Paralllement, les clients aussi se sont diversifs, et je constatais que le primtre
dutilisation des bases de donnes stendait. Au dbut rserv linformatique de
gestion, les bases de donnes sont petit petit apparues dans les secteurs de linfor-
matique industrielle et de linformatique mobile. Ces secteurs ntant pas forcment
coutumiers de ces technologies, ils ont fait appel des gens comme moi pour les
conseiller dans leur volution.
Aimant varier les plaisirs, outre les bases de donnes, je dveloppe en C/C++, par-
fois en environnement contraint du point de vue des performances. Cest proba-
blement de l que me vient cette curiosit qui me pousse comprendre comment
fonctionnent les choses et qui a pour suite naturelle loptimisation. Ajoutez cela le
plaisir de partager ses connaissances et vous comprendrez comment est n ce livre,
qui jespre vous aidera dans votre travail.
Laurent Navarro, dveloppeur dapplications, est bas Toulouse et travaille
depuis quinze ans avec des bases de donnes Oracle mais aussi quelques autres
(SQL Server, MySQL,etc.).
Il anime des formations SQL, PL/SQL, Pro*C et Tuning SQL depuis une dizaine
dannes.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Introduction
Pourquoi ce livre, qui s'adresse-t-il?
Loptimisation de bases de donnes est un problme la fois simple et compliqu.
Jinterviens souvent auprs de structures qui nont aucune notion doptimisation et,
dans ces cas-l, les choses sont plutt simples car lapplication de principes de base
doptimisation amliore rapidement la situation. En revanche, lorsque ces principes
de base ont dj t appliqus, la tche peut tre plus ardue
Lobjectif de cet ouvrage est de fournir les bases de loptimisation. Il explique ce qui
se passe dans la base de donnes afn que vous puissiez comprendre ce qui se passe
sous le capot de votre SGBDR et, ainsi, vous permettre de choisir des solutions
doptimisation en ayant conscience des impacts de vos choix.
Il existe dj des livres couvrant ce domaine, mais la plupart sont en anglais et
sadressent des DBA (administrateurs de base de donnes). Ces ouvrages sont soit
tellement pointus quun non-expert peut sy noyer, soit tellement lgers quon ne
comprend pas forcment pourquoi les choses sont censes samliorer. Cela rend
dlicate la transposition votre environnement. Jespre avoir trouv un juste milieu
avec cet ouvrage.
Pour moi, il est primordial daborder le problme de loptimisation ds la concep-
tion dun logiciel. Il est donc ncessaire que les dveloppeurs sapproprient ces
comptences plutt que de demander aux DBA de trouver des solutions aprs la
mise en production.
Ce livre sadresse donc en premier lieu aux quipes de dveloppement dve-
loppeurs, chefs de projet, architectes mais aussi, bien sr, aux DBA qui seront
toujours les interlocuteurs naturels des quipes de dveloppement ds quune base
de donnes sera utilise.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
2 Optimisation des bases de donnes
Quels sont les prrequis?
Pour lire cet ouvrage, il vous sufft de savoir ce quest une base de donnes relationnelle.
Une connaissance du SQL sera un plus.
Quel est le primtre de ce livre?
Ce livre couvre les cas les plus frquents, cest--dire des applications ayant au plus
quelques gigaoctets de donnes sur des serveurs classiques. Il ne couvre donc pas
des sujets comme lutilisation de GRID, de RAC ou des bases OLAP, mme si de
nombreux thmes abords ici sont prsents dans ce type dapplication aussi.
Cet ouvrage se focalise sur loptimisation autour du dveloppement. Les optimi-
sations au niveau de linfrastructure de la base de donnes ne seront que trs peu
abordes. Dautres livres plus orients sur lexploitation traitent dj ce sujet bien
mieux que je ne saurais le faire.
Organisation du livre
Cet ouvrage sarticule autour de neuf chapitres, regroups dans trois parties:
Le Chapitre 1 est une introduction visant prsenter brivement quelques
mcanismes internes des SGBDR qui seront ncessaires la comprhension des
chapitres suivants.
La premire partie concerne le premier axe doptimisation : celle du modle de
donnes.
Le Chapitre 2 rappelle ce quest le modle relationnel et traite les problma-
tiques lies au typage des donnes.
Le Chapitre3 traite de lintrt de la normalisation des bases de donnes et de
lutilit que peut prsenter la dnormalisation applique bon escient.
La deuxime partie concerne le deuxime axe doptimisation: celle des requtes.
Le Chapitre4 prsente les mthodes et loutillage. Il traite des diffrents outils
votre disposition pour analyser les situations et explique comment comprendre
les rsultats.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Introduction 3
Le Chapitre 5 dcrit lensemble des objets doptimisation et le cadre de leur
utilisation. Il dcrit les diffrents types dindex et dorganisation des tables ainsi
que leurs cas dusage.
Le Chapitre 6 prsente les impacts des variantes dcriture et dcrit quelques
bonnes et mauvaises pratiques.
Le Chapitre7 introduit les hints quil faut utiliser avec parcimonie, un ensemble
de techniques SQL avances ainsi que des optimisations du PL/SQL.
La troisime partie contient dautres axes doptimisations.
Le Chapitre8 traite des optimisations applicatives autres que loptimisation des
requtes elles-mmes.
Le Chapitre 9 aborde brivement quelques optimisations envisageables au
niveau de linfrastructure.
Ressources en ligne
Afn dillustrer les concepts prsents tout au long de ce livre, nous allons les appliquer
une base de test.
Cette base (structure et donnes) est disponible pour les SGBDR Oracle, SQL Server
et MySQL sur le site de lauteur, ladresse http://www.altidev.com/livres.php.
Remerciements
Merci ma femme Bndicte et mon fls Thomas pour leur soutien et leur patience
durant lcriture de ce livre. Merci ma mre Ginette pour ses relectures. Merci
mes relecteurs, Emmanuel et Nicole. Merci mon diteur, Pearson France, et parti-
culirement Patricia pour mavoir fait confance et Amandine pour ses prcieux
conseils. Merci lquipe dIris Technologies pour mavoir donn lide de ce livre
en me permettant danimer des formations sur ce sujet.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
1
Introduction aux SGBDR
Pour optimiser une base Oracle, il est important davoir une ide de la manire dont
elle fonctionne. La connaissance des lments sous-jacents son fonctionnement
permet de mieux comprendre ses comportements. Cest pourquoi nous commen-
cerons, ce chapitre, par vous prsenter ou vous rappeler brivement ce quest un
SGBDR et quelques-uns des lments qui le composent. Ces notions vous seront
utiles tout au long du livre. Le but ici nest pas de faire de vous un spcialiste du
fonctionnement interne dOracle, mais de vous donner quelques explications sur des
concepts que nous rfrencerons ultrieurement.
Si vous tes DBA, vous pouvez vous rendre directement au Chapitre2.
1.1 Qu'est-ce qu'une base de donnes?
Une base de donnes est un ensemble dinformations structures. Elle peut tre de
nature:
hirarchique;
relationnelle;
objet;
documentaire;

Actuellement, le march est principalement compos de bases de donnes relation-
nelles avec, parfois, une extension objet. Cet ouvrage traite exclusivement de ce type
de bases.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
6 Optimisation des bases de donnes
Dans les bases de donnes relationnelles, les donnes sont organises dans des
tables deux dimensions, conformment au modle relationnel que nous tudierons
au Chapitre 2.
1.1.1 Systme de gestion des bases de donnes
Un SGBDR (systme de gestion de base de donnes relationnelle) est un systme
(logiciel) qui permet de grer une base de donnes relationnelle. Les SGBDR peu-
vent tre soit de type client/serveur (Oracle, SQL Server, MySQL, PostgreSQL,
etc.), soit de type fchiers partags (Access, SQL Server CE, Paradox, DBase, etc.).
Dans le milieu professionnel, on retrouve principalement des SGBDR client/ser-
veur mme si les solutions en fchiers partags ont eu leur heure de gloire et sont
encore utilises dans certaines applications. Lapparition de SGBDR client/serveur
gratuits a fortement contribu populariser ce modle ces dernires annes. Le
modle client/serveur ncessite gnralement la prsence dun serveur, qui traite les
requtes transmises par le client et lui retourne le rsultat. Le principal intrt dun
SGBDR est quil va fournir les services suivants (tous les SGBDR ne proposent pas
tous ces services):
implmentation du langage d'interrogation des donnes SQL (Structured Query
Language);
gestion des structures des donnes et de leur modifcation;
gestion de lintgrit des donnes;
gestion des transactions;
gestion de la scurit, contrle daccs;
abstraction de la plateforme matrielle et du systme dexploitation sous-jacent;
du point de vue logique, abstraction de lorganisation du stockage sous-jacent;
tolrance aux pannes et administration du systme;
rpartition de la charge.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 1 Introduction aux SGBDR 7
1.2 Modle de stockage des donnes
1.2.1 Organisation des donnes
Les tables sont les objets logiques de base du modle relationnel. Or, un systme
dexploitation ne connat que la notion de fchiers. Le SGBDR permet de faire le
lien entre la reprsentation logique et le stockage physique dans les fchiers. Nous
allons voir comment en tudiant le SGBDR Oracle.
Les objets logiques (tables, index, etc.) sont stocks dans des espaces logiques appe-
ls "tablespaces". Une base de donnes est constitue de plusieurs tablespaces, les-
quels sont composs dun ou de plusieurs fchiers appels "datafles". Ces fchiers
peuvent se trouver sur des disques diffrents.
tablespace
TBS_COMPTA
d:\OracleData\
DataFileCompta1.Ora
d:\OracleData\
DataFileCompta2.Ora
datafles :
Fichiers de donnes
Objets stocks dans
le tablespace et repartis
sur les datafles
Tablespace
Espace disque logique
Table
Index
Index
Index
Index
Table
Index
Index
Index
Table
Index
Index
Index
Figure1.1
Organisation des objets dans un tablespace compos de deux datafles.
Les objets sont attachs un seul tablespace mais ils peuvent, par contre, tre rpar-
tis sur plusieurs datafles (voir Figure 1.1). Il ny a aucun moyen dinfuer sur la
localisation des objets au niveau des datafles, il est seulement possible de dfnir le
tablespace associ un objet. (Les objets partitionns peuvent, eux, tre attachs
plusieurs tablespaces. Nous les tudierons au Chapitre5, section5.3.4, "Partition-
nement des donnes".)
Les datafles, et donc les tablespaces, sont constitus de blocs de donnes (data block),
dont la taille est confgure la cration du tablespace. Ce paramtre varie gnra-
lement entre 2Ko et 16Ko et, par dfaut, est de 4 ou 8Ko suivant la plateforme
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
8 Optimisation des bases de donnes
(au long de louvrage, nous retiendrons une taille de 8Ko qui est une valeur assez
communment utilise).
Chaque objet ou constituant dobjet ayant besoin de stockage sappelle un "seg-
ment". Par exemple, pour une table classique, il y a un segment pour la table elle-
mme, un segment pour chacun de ses index et un segment pour chacun de ses
champs LOB (voir Chapitre 2, section 2.2.1, "Les types sous Oracle").
Quand un segment a besoin despace de stockage, il alloue un extent, cest--dire un
ensemble de blocs de donnes contigus. Un segment est donc compos dun ensemble
dextents qui nont pas forcment tous la mme taille. (Les clauses INITIAL et NEXT
spcifes dans linstruction de cration de lobjet associ au segment permettent
dinfuer sur ces paramtres.) La Figure1.2 prsente la dcomposition hirarchique
dun segment en blocs de donnes. Il est noter que, si un segment na plus besoin
de lespace quil a prcdemment allou, il ne le libre pas ncessairement.
Figure1.2
Dcomposition
d'un segment en extents
puis en blocs.
8 K
8 K
8 K
8 K
8 K
8 K
8 Ko
8 Ko






8 Ko
8 Ko
o
o
o
o
o
o
8 Ko
8 Ko
8 K
8 K
8 K
8 K
8 K
8 K
8 Ko
8 Ko
o
o
o
o
o
o
8 Ko
8 Ko
8 K
8 K
8 K
8 K
8 K
8 K
8 Ko
8 Ko
o
o
o
o
o
o
8 Ko
8 Ko
8 Ko
8 Ko
8 Ko
8 Ko
8 Ko
8 Ko
8 Ko
8 Ko
Blocs de donnes
(data block)
Extent Initial
128 Ko
Extent
64 Ko
Extent
64 Ko
Segment
256 Ko
MS SQL Server
Sous SQL Server, la logique est relativement proche, sauf qu'un niveau supplmentaire
est intgr, le niveau base de donnes (database). la diffrence d'Oracle, une instance
SQL Server contient plusieurs bases de donnes, qui ont chacune leurs espaces logiques
nomms data fle group (quivalents des tablespaces) eux-mmes composs de data fle.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 1 Introduction aux SGBDR 9
MySQL
Sous MySQL, l'organisation du stockage est dlgue au moteur de stockage. Plusieurs
moteurs sont supports, MyISAM et InnoDB le plus frquemment.
Le moteur MyISAM attribue plusieurs fchiers chaque table.
Un fchier .frm pour dcrire la structure de la table. Ce fchier est gr par MySQL et
non pas par le moteur de stockage. Un fchier .myd qui contient les donnes.
Un fchier .myi qui contient les index.
Le moteur InnoDB implmente le concept de tablespace qui contient tous les lments de
la base de donnes (tables, index, etc.). Les fchiers .frm grs par MySQL sont prsents
en plus du tablespace.
Les blocs de donnes contiennent les enregistrements (lignes ou row) et des struc-
tures de contrle. La Figure 1.3 montre un schma complet de lorganisation du
stockage des donnes.
Figure1.3
Schma illustrant le stockage
des donnes dans une base
Oracle.
Datafle
Segment (Table)
I
n
i
t
i
a
l
-
E
x
t
e
n
t
N
e
x
t
-
E
x
t
e
n
t
N
e
x
t
-
E
x
t
e
n
t
N
e
x
t
-
E
x
t
e
n
t
Extent
B
l
o
c

d
e

d
o
n
n

e
s
B
l
o
c

d
e

d
o
n
n

e
s
B
l
o
c

d
e

d
o
n
n

e
s
B
l
o
c

d
e

d
o
n
n

e
s
B
l
o
c

d
e

d
o
n
n

e
s
B
l
o
c

d
e

d
o
n
n

e
s
Bloc de donnes
Espace libre
Enregistrement
En-
tte
de
bloc
Enregistrement dcompos
En-tte
Taille
Donne
Donne
Taille
Donne
Donne
Taille
Donne
Donne
Table
Tablespace Segments
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
10 Optimisation des bases de donnes
1.2.2 Le RowID
Le RowID (identifant de ligne) est une information permettant dadresser direc-
tement un enregistrement, sans avoir parcourir aucune liste. Cest une sorte de
pointeur. Il est compos de:
lidentifant de lobjet;
lidentifant du datafle;
lidentifant du bloc dans le datafle;
lidentifant de la ligne dans le bloc.
Cette information sera rarement manipule directement par vos applications. Elle
est surtout destine un usage interne au SGBDR. Cependant, dans certains cas, il
peut tre intressant dy recourir depuis une application, par exemple pour dsigner
un enregistrement nayant pas de cl primaire ou pour adresser plus rapidement un
enregistrement pour lequel vous avez rcupr le RowID. Le RowID dun enregis-
trement sobtient en interrogeant la pseudo-colonne rowid.
SQL> select nocmd, noclient, datecommande, rowid from cmd;
NOCMD NOCLIENT DATECOMMANDE ROWID
---------- ---------- ------------ ------------------
14524 106141 16/04/2004 AAARnUAAGAAASIfAAG
14525 131869 16/04/2004 AAARnUAAGAAASIfAAH
14526 83068 16/04/2004 AAARnUAAGAAASIfAAI
14527 120877 16/04/2004 AAARnUAAGAAASIfAAJ
14528 34288 16/04/2004 AAARnUAAGAAASIfAAK
14529 103897 16/04/2004 AAARnUAAGAAASIfAAL
6 rows selected
Voir lAnnexeA, sectionA.1, pour plus dinformations sur les RowID.
1.2.3 Online Redo Log et Archived Redo Log
Les fchiers Online Redo Log sont des fchiers binaires qui contiennent toutes les
modifcations appliques aux datafles rcemment. Ils permettent notamment de
rparer les datafles en cas darrt brutal de la base.
Les fchiers Archived Redo Log sont des fchiers Redo Log archivs. Ils sont crs
uniquement si le mode archivelog est actif. Ils permettent de rparer les datafles,
de complter une restauration, de maintenir une base de secours en attente (stand
by database) et sont aussi ncessaires pour certaines fonctions Oracle Warehouse.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 1 Introduction aux SGBDR 11
Leur gestion a un cot en termes despace disque utilis, donc si vous nen avez pas
besoin, dsactivez cette fonction.
MS SQL Server
Les fchiers LDF, qui sont les journaux de transactions, jouent un rle analogue aux Online
Redo Log.
MySQL
Le moteur InnoDB intgre un mcanisme analogue aux Online Redo Log. Le moteur MyI-
SAM n'a pas d'quivalent.
1.2.4 Organisation des tables
Les donnes sont organises dans des tables deux dimensions: les colonnes, ou
champs, qui ne sont pas supposes voluer diffremment du modle de donnes, et
les lignes, enregistrements qui varient au fl du temps quand des donnes sont ajou-
tes ou modifes. Par dfaut, dans de nombreux SGBDR, la structure de stockage
adopte est une structure dite de "tas" (heap).
Ce type de structure stocke les enregistrements en vrac, sans ordre particulier, dans
une zone de donnes. Quand un enregistrement est dtruit, il libre de lespace quun
autre enregistrement pourra ventuellement rutiliser.
Sous Oracle, en mode MSSM (Manual Segment Space Management), les blocs
contenant de lespace libre, cest--dire dont le pourcentage despace libre est sup-
rieur au paramtre PCTFREE de la table, sont lists dans une zone de la table nomme
FREELIST. Les blocs dans lesquels de lespace a t libr la suite de suppressions
denregistrements et dont le pourcentage despace utilis repasse en dessous de la
valeur du paramtre PCTUSED sont, eux aussi, rpertoris dans la FREELIST.
Lorganisation des tables sous forme dindex est assez commune, les enregistre-
ments sont stocks dans lordre de la cl primaire. On dit alors que la table est orga-
nise en index (IOT, Index Organized Table). Nous tudierons ce type de table au
Chapitre5, section5.3.2, "Index Organized Table".
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
12 Optimisation des bases de donnes
MS SQL Server
Les tables sans index clustered sont organises en tas, celles ayant un index clustered ont
une organisation de type IOT.
MySQL
Sous MySQL, les tables utilisant le moteur MyISAM sont organises en tas, celles utilisant
le moteur InnoDB ont une organisation de type IOT.
1.2.5 Row Migration et Row Chaining
La migration denregistrement (Row Migration) est le mcanisme qui dplace un
enregistrement qui ne tient plus dans son bloc, aprs une mise jour de ses don-
nes ayant entran un accroissement de sa taille. Lors de la migration, le SGBDR
insre un pointeur lemplacement initial de lenregistrement qui dsigne le nouvel
emplacement que le SGBDR alloue pour y placer les donnes. Ainsi, on pourra
toujours accder lenregistrement en utilisant le RowID initial qui reste valide.
Cependant, il faut noter que lutilisation de ce pointeur sera source dE/S (entres/
sorties) supplmentaires. En effet, laccs un enregistrement au moyen de son
RowID se fait habituellement en une lecture de bloc, alors que celui un enregistre-
ment ayant migr ncessite de lire deux blocs (celui qui est point par le RowID plus
celui qui est dsign par le pointeur). Afn de limiter lapparition de ce phnomne,
Oracle ninsre des lignes dans un bloc que si un certain pourcentage despace libre
demeure lissue de cette opration (paramtre PCTFREE de la table; par dfaut, il
vaut 10%).
Le chanage denregistrement (Row Chaining) est le mcanisme qui gre le fait
quun enregistrement ne peut pas tenir dans un unique bloc de donnes (8Ko par
dfaut) car sa taille est suprieure. Le processus va scinder les donnes et les rpar-
tir dans plusieurs blocs en plaant dans chaque bloc un pointeur vers les donnes
situes dans le bloc suivant. Comme lors de la migration denregistrement, ce mca-
nisme va causer des E/S supplmentaires.
Voir lAnnexeA, sectionA.2, pour plus dinformations sur ces mcanismes.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 1 Introduction aux SGBDR 13
1.2.6 Le cache mmoire
Les accs disque sont trs lents compars aux accs en mmoire vive (RAM).
Approximativement et en simplifant : un disque dur a un temps daccs qui se
compte en millisecondes, alors que celui de la mmoire se compte en nanosecondes.
La mmoire vive est donc un million de fois plus rapide que les disques durs.
Par ailleurs, la quantit de mmoire vive sur les serveurs tant de plus en plus impor-
tante, une optimisation assez vidente consiste implmenter un systme de cache
mmoire dans les SGBDR.
Le but du cache mmoire est de conserver en mmoire une copie des informations
les plus utilises afn de rduire les accs au disque dur. Sous Oracle, ces caches
mmoire se trouvent dans SGA (System Global Area), une zone mmoire principale,
qui englobe diverses zones, parmi lesquelles:
Database Buffer Cache. Contient les blocs manipuls le plus rcemment.
Shared Pool. Contient les requtes rcentes ainsi que le plan dexcution qui
leur est associ. Cette zone contient aussi un cache du dictionnaire des donnes.
Le buffer cache contient une copie mmoire des blocs les plus manipuls afn de
rduire le nombre daccs disque. Cela aura pour effet damliorer notablement les
performances. Dans de nombreux cas, la quantit de mmoire disponible pour le
buffer cache sera plus faible que celle des donnes manipules. De fait, il faudra
choisir quelles sont les donnes conserver dans le cache et quelles sont celles qui
doivent cder leur place de nouvelles donnes. Ce choix sera fait par un algorithme
de type MRU (Most Recently Used) qui privilgiera le maintien en mmoire des
blocs les plus utiliss rcemment. Afn dviter que le parcours dune grosse table
entrane un renouvellement complet du cache, laccs ce type de tables est pondr
dfavorablement au proft des petites tables, pondres, elles, positivement. Ces der-
nires resteront plus longtemps dans le cache, alors que, gnralement, les grosses
tables ny seront pas charges entirement.
MS SQL Server
Sous SQL Server, on retrouve un mcanisme tout fait similaire.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
14 Optimisation des bases de donnes
MySQL
Sous MySQL, les choses sont un peu diffrentes. On retrouve bien un mcanisme de cache,
mais d'une nature diffrente. Le cache de requte permet de garder en cache le rsultat
des requtes prcdemment excutes.
Le cache mmoire correspondant au buffer cache d'Oracle est, lui, de la responsabilit du
moteur de stockage:
Le moteur MyISAM n'en a pas. Il part du principe que le systme d'exploitation en
possde un et qu'il sera tout aussi effcace d'utiliser celui-l. Cette solution est un peu
moins intressante mais elle a l'avantage de simplifer le moteur de stockage.
Le moteur InnoDB intgre, lui, un cache mmoire similaire, sur le principe au buffer
cache d'Oracle.
1.3 Intrt des index dans les SGBDR
Nous avons vu prcdemment que, dans une table organise en tas, les donnes
nont pas dordre particulier. Lorsque le SGBDR cherche une information suivant
un critre particulier (on parle de cl de recherche), il na pas dautre choix que de
parcourir lensemble des enregistrements pour trouver ceux qui rpondent au critre
demand. Vous imaginez aisment que, lorsquil y a beaucoup denregistrements,
cette mthode nest pas trs intressante. Cest pour rpondre plus effcacement ce
genre de besoin que la notion dindex a t introduite dans les SGBDR. Un index de
base de donnes ressemble un peu lindex de ce livre. Il contient une liste ordonne
de mots et une rfrence vers la page qui les contient. De plus, lindex est bien plus
petit que le livre.
Si nous retranscrivons cela en termes de base de donnes, un index contient la cl
de recherche et une rfrence vers lenregistrement. Son principal avantage est quil
est ordonn. Cela permet dy appliquer des techniques de recherche par dichotomie,
beaucoup plus effcaces que les recherches linaires ds que le nombre denregis-
trements slve.
Les index sont intressants avec les tables organises en tas. Cependant, le besoin
est le mme avec les tables organises suivant des index (IOT) qui sont dj tries.
En effet, si lordre de la table nest pas celui de la cl de recherche, le problme
reste entier. Par exemple, si vous grez une liste de personnes trie par numro de
Scurit sociale, lorsque vous faites une recherche sur le nom, vous ntes pas plus
avanc que la liste soit trie par numro de Scurit sociale ou pas trie du tout.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 1 Introduction aux SGBDR 15
Lintrt des index est donc indpendant du type dorganisation de table. Nous tu-
dierons en dtail au Chapitre 5, section 5.2.1, "Index B*Tree", les index B*Tree,
les plus communs. Par la suite, nous aborderons les principaux types dindex
disponibles.
1.4 Analyse du comportement du SGBDR
1.4.1 Excution d'une requte SQL
Toute requte SQL envoye au SGBDR suit le mme parcours afn dtre excute.
Nous allons tudier ici ce cheminement afn de comprendre comment le SGBDR
passe dune requte SQL un ensemble de donnes rsultat.
Il faut bien avoir en tte que le SQL, contrairement la plupart des langages infor-
matiques, ne dcrit pas la faon de dterminer le rsultat mais quil permet dexpri-
mer un rsultat attendu. Ainsi, il nexplique pas comment manipuler les tables, mais
les liens quil y a entre elles et les prdicats appliquer sur les donnes. Le SGBDR
doit trouver le meilleur moyen de rpondre une requte SQL.
tape 1: Parsing et traduction en langage interne
Cette tape consiste interprter le texte de la requte (parsing) et effectuer des
contrles syntaxiques. Le SGBDR vrife si la requte respecte la grammaire dune
requte SQL et si les mots cls sont bien placs. Cette tape inclut aussi les contrles
smantiques, cest--dire que le SGBDR vrife si la requte manipule bien des
tables et des colonnes qui existent et si lutilisateur possde les droits permettant de
faire ce qui est demand dans la requte.
tape 2: tablissement d'un plan d'excution
Le plan dexcution est la faon dont le SGBDR parcourt les diffrents ensembles
de donnes afn de rpondre la requte. Nous tudierons au Chapitre 4, sec-
tion4.1.2, "Comprendre le plan dexcution", les lments primaires constituant un
plan dexcution.
Lors de cette tape, le SGBDR tablit plusieurs plans dexcution possibles. En
effet, tout comme il y a plusieurs algorithmes possibles pour crire un programme,
il y a plusieurs plans dexcution possibles pour rpondre une requte.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
16 Optimisation des bases de donnes
Ensuite, loptimiseur (voir section 1.4.2) choisi le plan dexcution quil estime tre
le meilleur pour excuter la requte, parmi les diffrents plans dexcution possibles.
tape 3: Excution de la requte
Cette tape consiste excuter le plan dexcution dfni ltape prcdente, cest-
-dire aller chercher les informations dans les tables en passant par les chemins
dfnis par le plan dexcution et en extraire le rsultat demand.
La technique du binding que nous tudierons au Chapitre8, section8.3, "Utilisation du
binding" permet, lorsqu'une mme requte est excute plusieurs fois avec des paramtres
diffrents, de n'excuter qu'une seule fois les tapes1 et2 et ainsi de passer directement
l'tape3 lors des excutions suivantes.
1.4.2 Optimiseur CBO (Cost Based Optimizer)
Le rle de loptimiseur est de trouver le plan dexcution le plus performant pour
excuter une requte. Oracle est depuis la version7 (dbut des annes 1990) pourvu
de deux optimiseurs de requtes:
celui qui est bas sur des rgles (RBO, Rule Based Optimizer, introduit en V6);
celui qui est bas sur les cots (CBO, Cost Based Optimizer, introduit en V7).
Sur les versions rcentes dOracle, loptimiseur bas sur les rgles nexiste plus
vraiment. Les mots cls permettant la manipulation du RBO sont seulement pr-
sents des fns de rtrocompatibilit (depuis la version10g, le RBO nest plus sup-
port). Oracle recommande, depuis plusieurs versions, de ne plus utiliser le RBO et
concentre tous ses efforts sur le CBO, cest donc celui-l que nous allons tudier.
MS SQL Server et MySQL
SQL Server et MySQL tant eux aussi munis d'un optimiseur de type CBO, les grands prin-
cipes tudis ici seront communs.
Le CBO est un optimiseur qui est bas sur lestimation des cots dexcution des
oprations des plans dexcution. Pour une requte donne, le SGBDR tablit plu-
sieurs plans dexcution possibles, et le CBO estime pour chacun deux le cot
dexcution et choisit le moins lev.
INFO
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 1 Introduction aux SGBDR 17
Comment estimer le cot dun plan dexcution ? Le SGBDR value le cot en
ressources utilises pour excuter ce plan. Ces ressources sont:
le temps CPU;
le nombre dE/S (entres/sorties) disque dur (I/O en anglais);
la quantit de mmoire vive (RAM) ncessaire.
Le cot sera une synthse entre lutilisation du CPU et le cot des E/S, selon quil
sagit daccs squentiels (lecture de plusieurs blocs contigus) ou daccs alatoires
(lecture monobloc).
Cependant, vous imaginerez aisment que ce cot dpend non seulement de la
requte elle-mme, mais aussi des donnes sur lesquelles elle porte. En effet, cal-
culer le salaire moyen dune table contenant 10personnes sera moins coteux que
de calculer la mme moyenne sur une table dun million de personnes alors que la
requte sera la mme.
Pour estimer le cot dune requte, le SGBDR a besoin de dterminer, pour chacune
des tapes du plan dexcution, le nombre denregistrements concerns, cest--dire
la cardinalit de lopration. Cette cardinalit dpend des donnes elles-mmes mais
aussi de limpact de chacune des conditions. Par exemple, une condition qui fltre
sur un numro de Scurit sociale naura pas le mme impact sur la cardinalit
quune condition portant sur un dpartement ou une anne de naissance. Ce principe
se nomme la slectivit, nous ltudierons au Chapitre5, section5.1.3, "Slectivit,
cardinalit, densit".
Loptimiseur dtermine le cot de chaque plan daction dexcution. Pour cela, sans
excuter aucun deux, ni parcourir les donnes, il dfnit les cardinalits de chaque
opration partir de statistiques sur les donnes (voir Chapitre5, section5.1, "Statis-
tiques sur les donnes").
Loptimiseur cherche dterminer le meilleur plan ; cependant, la notion de
"meilleur" peut, dans certains cas, diffrer en fonction de lobjectif, lOptimizer
Goal, qui peut tre de deux types:
First_Rows (premires lignes);
All_Rows (toutes les lignes).
First_Rows privilgie le temps de rponse pour retourner les premires lignes. Cela
peut tre intressant dans le cadre dapplications interagissant avec des utilisateurs.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
18 Optimisation des bases de donnes
Pourtant, la meilleure solution choisie pour cet objectif peut se rvler moins int-
ressante si, fnalement, on ramne toutes les lignes.
All_Rows, lui, privilgie lutilisation optimale des ressources. Il considre le temps
de rponse pour retourner lensemble des lignes.
Il existe aussi des variantes lobjectif First_Rows, ce sont les objectifs First_
Rows_n, o n est une des valeurs suivantes: 1,10, 100, 1000. Dans ce cas, loptimi-
seur privilgie le temps de rponse permettant de retourner les n premires lignes.
Lobjectif de loptimiseur (Optimizer Goal) peut se dfnir diffrents niveaux:
celui de la confguration de linstance, travers le paramtre dinitialisation
OPTIMIZER_MODE.
celui de la session utilisateur, en agissant sur le mme paramtre:
ALTER SESSION SET optimizer_mode = rst_rows_10;
celui dune requte, en utilisant les hints que nous tudierons plus tard:
Select /*+FIRST_ROWS(10) */ * from commandes
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Axe 1
tude et optimisation
dumodle de donnes
Cette partie aborde laspect conception des bases de donnes en replaant les bases
de donnes relationnelles dans le contexte du modle relationnel.
Elle a pour but de vous rappeller quelques rgles, mais ne prtend nullement se subs-
tituer des ouvrages traitant de la conception de bases de donnes tels que:
Cration de bases de donnes de Nicolas Larrousse (Pearson, 2006);
SQL de Frdric Brouard, Rudi Bruchez, Christian Soutou (Pearson, 2008, 2010)
(les deux premiers chapitres traitent de la conception de bases de donnes).
Lapplication de mthodes de conception, telles que Merise, permettra davoir une
dmarche de conception structure et contribuera obtenir un modle de donnes
pertinent et sans cueils de performances majeurs.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
2
Modle relationnel
2.1 Prsentation
Les bases de donnes relationnelles que nous tudions sont fondes sur le modle
relationnel invent par Edgar Frank Codd en 1970 (dcrit dans la publication ARela-
tional Model of Data for Large Shared Data Banks) et largement adopt depuis.
Ce modle sappuie sur lorganisation des donnes dans des relations (aussi appeles
"entits"), qui sont des tables deux dimensions:
Les colonnes. Ce sont les attributs qui caractrisent la relation.
Les lignes. Aussi nommes "tuples", elles contiennent les donnes.
Lordre des tuples na aucune importance ni signifcation.
Tableau2.1: Exemple d'une relation contenant des employs
Nom Prnom Service Localisation
DUPOND Marcel Comptabilit Toulouse
DURAND Jacques Production Agen
LEGRAND Denis Ventes Toulouse
MEUNIER Paul Production Agen
MEUNIER Paul Achats Agen
NEUVILLE Henry Ventes Toulouse
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
22 tude et optimisation dumodle de donnes Axe 1
Le modle relationnel tablit quil doit tre possible didentifer un tuple de faon
unique partir dun attribut ou dun ensemble dattributs, lesquels constituent la cl
de la relation. Une cl est dite "naturelle" si un attribut ou un ensemble dattributs
la constituent. Dans lexemple prcdent, on constate quil est dlicat den trouver
une car se pose le problme des homonymes qui, dans le pire des cas, pourraient
travailler dans le mme service. Lorsquune cl naturelle nexiste pas, on introduit
un nouvel attribut identifant qui en fera offce. Il sagit, dans ce cas, dune cl
technique. Cet identifant peut tre un numro affect squentiellement. On recourt
aussi lutilisation de cl technique quand la cl naturelle est trop grande ou pour
des raisons techniques, par exemple des problmes de changement de valeur de la
cl lorsquil y a des relations matre/dtails et que le SGBDR ne gre pas la mise
jour en cascade.
Labsence de cl primaire dans une relation doit tre exceptionnelle (moins de 1%
des tables). Lorsque rien ne sy oppose, il faut privilgier lutilisation de cl naturelle.
On peut parfois avoir plusieurs cls pour identifer un tuple (cest systmatique si
vous ajoutez une cl technique alors quil y a une cl naturelle). Toutes ces cls
sont dites "candidates" et celle qui a t retenue pour identifer la relation est dite
"primaire".
Tableau2.2: Exemple d'une relation contenant des employs avec un identifant
Identifant Nom Prnom Service Localisation
5625 DUPOND Marcel Comptabilit Toulouse
8541 DURAND Jacques Production Agen
4521 LEGRAND Denis Ventes Toulouse
8562 MEUNIER Paul Production Agen
7852 MEUNIER Paul Achats Agen
6214 NEUVILLE Henry Ventes Toulouse
Un des grands intrts du modle relationnel est quil rpartit lensemble des donnes
dans diffrentes relations et tablit des associations entre ces relations au moyen de
leur cl primaire. Ce principe permet dviter la duplication dinformation et donc
davoir des donnes plus consistantes (voir Tableaux 2.3 et 2.4).
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 2 Modle relationnel 23
Tableau2.3: Exemple d'une relation "Employ", contenant des employs,
avec une association un service
IdEmploy Nom Prnom IdService
5625 DUPOND Marcel 100
8541 DURAND Jacques 120
4521 LEGRAND Denis 150
8562 MEUNIER Paul 120
7852 MEUNIER Paul 180
6214 NEUVILLE Henry 150
Tableau2.4: Exemple d'une relation "Service"
IdService NomService Localisation
100 Comptabilit Toulouse
120 Production Agen
150 Ventes Toulouse
180 Achats Agen
Le modle relationnel a t conu pour tre utilis avec une algbre relationnelle qui
permet deffectuer des oprations sur les entits. Les principales sont:
La jointure. Relie deux entits par leur association.
La slection. Filtre les tuples dont les attributs rpondent un prdicat.
La projection. Slectionner seulement certains attributs dune entit.
Cette algbre a t implmente puis tendue dans les SGBDR au moyen du langage
SQL. Nous nallons pas nous tendre sur la thorie de lalgbre relationnelle qui,
mme si elle en constitue les bases, est par moments assez loigne de ce quon peut
faire avec du SQL.
En termes de gnie logiciel, il est plutt question de modle conceptuel des donnes
(MCD). Lorsque celui-ci est bas sur le modle relationnel, on parle alors de modle
entit/association (et non pas de modle entit/relation, qui est une traduction erro-
ne du terme anglais entity-relationship model). La mthode MERISE, qui a berc
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
24 tude et optimisation dumodle de donnes Axe 1
des gnrations dinformaticiens, utilise gnralement ce modle pour reprsenter le
MCD. Ainsi, en France, on dsigne souvent par MCD le modle entit/association.
La mthode MERISE parle aussi de modle logique des donnes (MLD) qui est
trs proche de limplmentation fnale en base de donnes. Le MLD est une version
indpendante du SGBDR du MPD (modle physique des donnes). Le MLD et le
MPD sont souvent confondus, dautant plus quand la base reprsente nest prvue
que pour tre implmente sur un SGBDR.
Le MCD et le MPD sont deux modles la fois redondants et complmentaires.
Ils dcrivent tous deux une base de donnes, mais avec des niveaux de dtail et
dabstraction diffrents. Le MCD se veut plus conceptuel, par exemple:
Il dsigne les entits par leur nom logique et non pas par le nom de la table.
Les associations sont nommes par un verbe.
Il peut contenir des associations entre les entits qui ne seront pas implmentes
par la suite sous forme de cl trangre dans la base de donnes.
Il ne rpte pas les cls ncessaires aux associations et ne fait pas apparatre le
fait quune table est ncessaire pour implmenter une relationM-N.
Le MCD se veut indpendant des bases de donnes, il utilise donc des types de
donnes "universels". La plupart des outils de modlisation peuvent convertir
automatiquement des MCD en MPD mais, gnralement, le rsultat ncessite
dtre retouch. Si vous convertissez sans aucune prcaution un MCD en MPD,
vous risquez davoir des tables qui sappellent "compose", par exemple, ou un autre
Figure2.1
Exemple de MCD
(diagramme
entit-association).
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 2 Modle relationnel 25
verbe qui a toute sa place dans un MCD mais qui est moins indiqu comme nom de
table.
Figure2.2
Exemple de MPD (modle physique des donnes).
Le MPD est propre une base de donnes et permet de gnrer automatiquement
les scripts de cration des tables. Il contient les noms des tables, lensemble des
champs (qui sappelaient "attributs" dans le MCD) avec leurs types et prcisions, les
contraintes dintgrit rfrentielle, les index, etc. Si votre base doit tre importante,
prvoyez de passer un peu de temps pour affner le MPD, laide, entre autres, de
ce que nous allons tudier au cours de cet ouvrage.
Les partisans du MCD disent que cest une phase indispensable, alors que ses dtrac-
teurs affrment quil ne sert rien. Personnellement, je pense que la vrit doit tre
quelque part entre les deux. Cela dpend des habitudes de chaque organisation, de
la taille de la base, des outils dont vous disposez et du niveau dabstraction souhait.
2.2 Les bons rfexes sur le typage des donnes
Le typage des donnes parat tre un sujet anodin mais il ne lest pas, et je suis sur-
pris parfois de voir des bases de donnes avec des types incorrectement choisis. La
conversion automatique du MCD en MPD peut tre une source de mauvais typage,
car les types "universels" ne proposent pas forcment la fnesse disponible avec le
SGBDR.
Il y a principalement quatre familles de types de champs:
numriques;
textes;
dates et heures;
binaires.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
26 tude et optimisation dumodle de donnes Axe 1
Pour les donnes alphanumriques, il ny aura pas trop dambigut. Le nom dune
personne devra tre mis dans un champ de type texte. Il existe gnralement trois
variantes de types textes qui peuvent avoir des incidences sur le stockage et la mani-
pulation des champs:
les types textes de longueur fxe (gnralement dsigns par char);
les types textes de longueur variable (gnralement dsigns par varchar);
les types textes de grande capacit (dsigns par text, bigtext ou CLOB).
Les champs de type texte de longueur fxe utilisent systmatiquement lespace cor-
respondant la longueur pour laquelle ils sont dfnis (hormis sur certains SGBDR
o le fait dtre NULL noccupe pas despace). Si la chane est plus petite que la
longueur de la colonne, elle sera complte par des espaces qui seront ventuelle-
ment supprims par le SGBDR ou par la couche daccs aux donnes. Ces champs
sont assez peu utiliss mais ils peuvent prsenter un intrt sur des colonnes qui
contiennent des valeurs de taille fxe. Lavantage de ce type est quil vite le sur-
cot li la gestion dun champ de longueur variable. Par contre, sa manipulation
provoque parfois des comportements droutants pour les dveloppeurs habitus aux
types varchar.
Le type texte de longueur variable (varchar) est le plus utilis. Il noccupe que
lespace ncessaire la donne plus quelques octets pour dfnir la longueur de
celle-ci.
Les types textes de grande capacit sont rserver aux champs qui en ont vraiment
besoin, cest--dire qui ont besoin de contenir plus de 4000caractres (cela dpend
des bases). Il en dcoule parfois une gestion du stockage trs spcifque qui peut
peser sur les performances et lespace utilis. De plus, certaines oprations sont
parfois interdites sur ces types.
Tous ces types existent gnralement aussi en version Unicode. Cependant, avec
la perce dUNICODE, certaines bases arrivent prsent grer le jeu de carac-
tres UNICODE comme nimporte quel autre jeu de caractres, rendant lintrt des
variantes UNICODE des types caractres moins vidents.
Concernant les donnes numriques, les SGBDR donnent plus ou moins de choix.
Ilsera judicieux de se poser quelques questions sur la nature et ltendue des valeurs
manipuler dans ces champs afn de choisir le type le plus appropri. Les principaux
types numriques sont:
les types entiers signs ou non signs, sur 8, 16, 32 ou 64bits;
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 2 Modle relationnel 27
les types dcimaux virgule fottante 32 ou 64bits;
les types dcimaux virgule fxe.
Chacun deux occupe plus ou moins despace. Il faut penser que les types virgule
fottante font des approximations qui peuvent introduire des dcimales supplmen-
taires ou en supprimer. Veillez garder de la cohrence avec le type des variables qui
manipuleront les donnes dans votre application (si votre application gre un oat,
il ne faut pas que la base dfnisse un entier 64bits et vice versa).
Concernant les identifants numriques, les types numriques ne sont pas toujours
le bon choix. Pour les identifants numriques squentiels, un type entier est un
choix adquat (prendre un type dcimal ne serait pas pertinent). Par contre, pour des
identifants tels que des numros de Scurit sociale (1551064654123), ce nest pas
forcment le meilleur choix, car:
Cest une valeur trop grande pour tenir sur un entier 32bits.
Les types fottants risquent de lapproximer.
Vous navez a priori aucune raison den faire la somme ou la moyenne.
Lordre alphabtique des identifants est le mme que lordre numrique car il y
a toujours 13chiffres.
Pour un tel identifant, je conseille plutt lusage dun type texte de longueur fxe. La
prsence de zros en tte didentifant peut tre un autre problme: ils seront effacs
si vous utilisez un type numrique. Par exemple, la valeur 000241 sera stocke, et
donc restitue, sous la forme 241 si vous utilisez un type numrique au lieu dun
type texte.
Concernant les donnes date et heure, il existe, suivant les SGBDR, des types per-
mettant de stocker une date seule ou une date et une heure avec une prcision plus
ou moins grande sur la rsolution, allant de quelques secondes des fractions de
seconde. Jai vu assez rgulirement des dveloppeurs ne pas utiliser ces types pour
stocker des dates mais prfrer des types textes. Largument avanc est que les types
date et heure sont parfois pnibles manier aussi bien en SQL que dans les envi-
ronnements de dveloppement. Je leur concde que cest souvent vrai. En effet,
une date est plus diffcile manipuler quun entier, mais ce nest cependant pas
insurmontable. Il faut juste sy pencher une bonne fois pour toutes, se faire une
feuille rcapitulative avec des exemples et, gnralement, aprs tout va bien. Reste
nanmoins le problme des fonctions de transformations en SQL qui ne sont pas
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
28 tude et optimisation dumodle de donnes Axe 1
portables dun SGBDR lautre. Si votre application doit fonctionner sur diffrents
SGBDR, il faudra faire une petite couche dabstraction.
Cela montre que le type date complique parfois un peu les oprations, mais quap-
porte-t-il par rapport un type texte? Si vous stockez dans la base avec une notation
ISO (AAAAMMJJ), vous conservez la facult de trier chronologiquement et de
travailler sur des intervalles. Par contre, si vous utilisez un format plus franais (ex:
JJ/MM/AAAA), le tri et le fltrage par plage seront beaucoup plus compliqus. Bien
videmment, le type date vous permettra deffectuer ce genre dopration et aussi
des choses quaucun de ces modes de stockage textuel ne permet en SQL, comme
soustraire des dates entre elles, ajouter ou soustraire des intervalles de temps. De
plus, en termes despace requis pour le stockage des donnes, les types dates seront
systmatiquement plus avantageux que leurs quivalents en format texte. Dernier
avantage, avec les types dates, vous avez la garantie de navoir que des dates valides
dans la base. Ce point est parfois considr comme un inconvnient: il peut arriver
que des applications rcuprent des chanes contenant des dates errones, ce qui
provoque des erreurs lors du chargement de la base de donnes. Par exprience, je
sais quavoir des dates invalides dans les tables pose des problmes; il vaut donc
mieux, le plus en amont possible, avoir des donnes valides.
Lutilisation dun entier pour stocker une date au format julien (nombre de jours
depuis le 1
er
janvier 4713 av. J.-C.) allie la plupart des atouts du format date
(ordre, intervalles, taille) mais prsente linconvnient de ne pas tre trs lisible
(2524594 = 1/1/2000). Il nest pas support de faon native par tous les SGBDR
et ne permet pas toujours de grer lheure. Lutilisation dun timestamp type unix
prsente les mmes caractristiques.
Les SGBDR grent gnralement dautres types de donnes, tels que les types
binaires permettant de manipuler des images, des sons ou des fchiers, des types XML
permettant de stocker du XML et de faire des requtes dessus, et quelques autres
types plus spcifques chaque SGBDR.
2.2.1 Les types sous Oracle
Pour grer les valeurs numriques sous Oracle, on utilise gnralement le type
NUMBER avec des prcisions variables suivant que lon souhaite un entier ou une
grande valeur dcimale. Sous Oracle, la taille du stockage dpend de la valeur et non
pas de la dfnition du champ. Ainsi, stocker la valeur1 prend moins de place que
stocker la valeur 123456789,123. Le type NUMBER peut prendre deux paramtres:
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 2 Modle relationnel 29
precision, qui correspond au nombre de chiffres signifcatifs maximal que les
valeurs du champ pourront avoir. Il peut prendre une valeur entre1 et38, ce qui
correspond aux chiffres de part et dautre du sparateur dcimal. Le symbole*
est quivalent la valeur38.
scale, qui correspond au nombre de chiffres signifcatifs maximal aprs la vir-
gule. Il vaut0 sil nest pas spcif: cest alors un moyen de dfnir un type entier.
Le type FLOAT est un sous-type du type NUMBER et ne prsente pas un intrt parti-
culier. Les types BINARY_FLOAT et BINARY_DOUBLE sont, eux, calqus sur les types
fottants"C" et occupent respectivement 4et8octets. Les types ANSI (INT, INTEGER,
SMALLINT) sont en fait des synonymes de NUMBER(38) qui reprsente un entier. DECIMAL
est un synonyme de NUMBER.
Les types caractres disponibles sont:
CHAR et NCHAR pour les textes de tailles fxes limit 2000caractres (NCHAR est
la version Unicode).
VARCHAR2 et NVARCHAR pour les textes de tailles variables limits 4000carac-
tres. VARCHAR est un synonyme de VARCHAR2.
CLOB et NCLOB pour les textes de grande taille, limits 4Go. Ces types sont trai-
ts comme un LOB (Large OBject). Les donnes sont stockes dans un segment
spar, mais sil y en a peu pour un enregistrement et que le stockage en ligne
est actif (voir Chapitre 5, section 5.3.1, "Gestion des LOB"), la donne pourra
tre stocke comme un VARCHAR. Le type LONG, anctre des CLOB, est obsolte et
ne doit plus tre utilis.
Les types dates disponibles sont:
DATE, qui permet de stocker date et heure avec une rsolution la seconde, occupe
un espace de 7octets. Il nexiste pas de type date seule, on utilise donc le type
date sans spcifer dheure, labsence dheure est traduite par minuit.
TIMESTAMP, qui permet de stocker date et heure avec une rsolution en fractions
de seconde jusqu une nanoseconde.
TIMESTAMP WITH TIME ZONE est analogue TIMESTAMP mais stocke en plus la
zone horaire.
Les types binaires disponibles sont:
RAW, pour les binaires de moins de 2000octets.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
30 tude et optimisation dumodle de donnes Axe 1
BLOB, pour les binaires de taille variable, limits 4Go. Concernant le stockage,
il fonctionne comme les CLOB.
LONG RAW, anctre de BLOB, ne doit plus tre utilis.
BFILE est analogue BLOB si ce nest que les donnes sont stockes dans le
systme de fchier du serveur gr par le systme dexploitation et non pas dans
un tablespace.
2.2.2 Les types sous SQL Server
Les types numriques disponibles sont:
BIT, pour les boolens, stock sur 1bit;
TINYINT, pour les entiers non signs de 8bits;
SMALLINT, INT, BIGINT, pour les entiers signs de respectivement 16, 32 et 64bits;
DECIMAL et NUMERIC, pour les dcimaux virgule fxe, stocks sur 5 17octets
suivant la prcision;
FLOAT, dcimaux virgule fottante, stock sur 4 8octets suivant la prcision,
REAL = FLOAT(24).
Les types caractres disponibles sont:
CHAR et NCHAR, pour les textes de taille fxe limits 8000caractres;
VARCHAR et NVARCHAR, pour les textes de taille variable limits 8000caractres;
TEXT, NTEXT, VARCHAR(max) et NVARCHAR(max), pour les textes de grande taille
limits 2Go.
Les types dates disponibles sont:
DATE, qui permet de stocker une date seule (depuis SQL Server 2008);
SMALLDATETIME, qui permet de stocker date et heure avec une rsolution dune
minute, stock sur 4octets;
DATETIME, qui permet de stocker date et heure avec une rsolution de trois
quatre secondes, stock sur 8octets;
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 2 Modle relationnel 31
DATETIME2, qui permet de stocker date et heure avec une rsolution en fractions
de seconde jusqu 100 nanosecondes, stock sur 6 8 octets suivant la rso-
lution (depuis SQL Server 2008);
TIME, qui permet de stocker une heure seule (depuis SQL Server 2008).
Les types binaires disponibles sont:
BINARY, pour les binaires de taille fxe de moins de 8000octets;
VARBINARY, pour les binaires de taille variable de moins de 8000octets;
IMAGE, pour les binaires jusqu 2 Go, remplac par VARBINARY(max) (depuis
SQL Server 2005).
2.2.3 Les types sous MySQL
Les types numriques disponibles sont:
BOOL, pour les boolens, stock sur 8bits.
TINYINT, pour les entiers non signs, stock sur 8bits.
SMALLINT, MEDIUMINT, INT, BIGINT, pour les entiers signs de respectivement 16,
24, 32 et 64bits. Il est possible dajouter le mot cl UNSIGNED pour manipuler des
entiers non signs. INTEGER est un synonyme de INT.
DECIMAL et DEC, dcimaux virgule fxe ayant une prcision jusqu 65chiffres
signifcatifs.
FLOAT, DOUBLE, dcimaux virgule fottante, stock sur 4 et 8octets.
Les types caractres disponibles sont:
CHAR, pour les textes de taille fxe limits 255caractres.
VARCHAR, pour les textes de taille variable limits 65535caractres.
TINYTEXT, TEXT, MEDIUMTEXT et LONGTEXT, pour les textes de taille variable limi-
ts respectivement 255octets, 64Ko, 16Mo, 4Go. Le choix du type permet de
fxer la taille du champ interne qui dfnit la taille de la donne.
Les types dates disponibles sont:
DATE, qui permet de stocker une date seule;
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
32 tude et optimisation dumodle de donnes Axe 1
DATETIME, qui permet de stocker date et heure avec une rsolution dune seconde,
stock sur 8octets;
TIMESTAMP, qui permet de stocker date et heure avec une rsolution dune seconde
sur une plage de 1970 2038, stock sur 4octets;
TIME, qui permet de stocker une heure seule.
Les types binaires disponibles sont:
TINYBLOB, BLOB, MEDIUMBLOB et LONGBLOB, pour les binaires de taille variable
limits respectivement 255 octets, 64Ko, 16Mo, 4Go;
BINARY, pour les binaires de taille fxe de moins de 255 Octets;
VARBINARY, pour les binaires de taille variable de moins de 64Ko.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
3
Normalisation,
base du modle relationnel
3.1 Normalisation
Le but de la normalisation est davoir un "bon" modle de donnes dans lequel les
donnes seront bien organises et consistantes. Un des grands principes est que
chaque donne ne doit tre prsente quune seule fois dans la base, sinon un risque
dincohrence entre les instances de la donne apparat.
Figure3.1
Modle physique des
donnes (MPD) de la base
de donnes initiale gre
par une feuille de tableur.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
34 tude et optimisation dumodle de donnes Axe 1
La normalisation dun modle relationnel sappuie sur des rgles dfnies dans les
diffrentes formes normales que nous allons tudier ci-aprs.
Nous allons mettre en pratique la normalisation en partant dune petite base de
donnes qui a pour but de grer une librairie. Celle-ci, au fl du temps, est devenue
une grande librairie et traite des centaines de commandes par jour. La "base de don-
nes" initiale tait gre sous un tableur et nest donc pas du tout normalise (voir
Figure 3.1).
3.1.1 Premire forme normale (1NF)
Pour qu'une entit soit en premire forme normale (1NF), elle doit:
avoir une cl primaire;
tre constitue de valeurs atomiques;
ne pas contenir d'attributs ou d'ensembles d'attributs qui soient des collections de
valeurs.
Un attribut qui a des valeurs atomiques nest pas dcomposable en sous-attributs. Par
exemple, un attribut NomPrenom nest pas considr comme atomique, puisquil
peut tre dcompos en deux attributs: Nom et Prnom.
Ne pas contenir dattributs ou densembles dattributs qui soient des collections de
valeurs signife que:
Il ne doit pas y avoir dattributs qui contiennent, en fait, plusieurs valeurs spa-
res par des caractres comme des espaces ou des virgules tels que "Dupond,
Durand, Leclerc".
Il ne doit pas y avoir densembles dattributs qui soient en fait des listes de
valeurs, tels que les attributs Article1, Article2, Article3, etc., de notre exemple.
De tels attributs doivent tre mis dans une entit spare qui aura une association de
type1-N avec celle qui contenait ces attributs.
Mettons en pratique la premire forme normale sur notre base exemple. Nous allons
crer une entit des lignes de commandes pour rsoudre le problme des collections
sur les attributs (Livre, Titre, Quantit, Prix) et atomiser les attributs NomPrenom et
Adresse. Cela donnera le rsultat suivant qui peut, raisonnablement, tre considr
comme 1NF. Nous proftons de cette tape pour enrichir un peu notre modle en
ajoutant lattribut ISBN.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 3 Normalisation, base du modle relationnel 35
Figure3.2
Modle physique
des donnes (MPD)
en premire forme
normale (1NF).
Il existe plusieurs notations graphiques des modles relationnels. Chaque outil choisit une
des notations en prenant parfois des ides d'une autre notation.
Les diagrammes prsents ce chapitre sont des MPD sans affchage des types, raliss avec
l'outil Toad Data Modeler, avec la notation IE qui utilise les conventions suivantes:
Ligne association pleine: association identifant dpendante;
Ligne association discontinue: association non-identifant dpendante;
L'extrmit rond plus triangle dsigne le ct flle de la relation;
Rectangle angles droits: table;
Rectangle angles arrondis: table flle d'une association identifant dpendante.
3.1.2 Deuxime forme normale (2NF)
Pour qu'une entit soit en deuxime forme normale (2NF), il faut:
qu'elle soit en premire forme normale (1NF);
que tous les attributs ne faisant pas partie de ses cls dpendent des cls candidates
compltes et non pas seulement d'une partie d'entre elles.
Cette forme ne peut poser de diffcults quaux entits ayant des cls composites
(composes de plusieurs attributs). Si toutes les cls candidates sont simples et que
lentit est 1NF, alors lentit est 2NF. Attention, la rgle sapplique toutes les cls
candidates et pas seulement la cl primaire.
la Figure 3.2, lentit lignescommandes nest pas 2NF car la cl est NoCom-
mande plus Livre. Or, les attributs Titre, Prix et ISBN ne dpendent que de lattri-
but Livre, donc, seulement dune partie de la cl. Pour transformer ce modle en
deuxime forme normale, nous allons crer une nouvelle entit qui contiendra les
INFO
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
36 tude et optimisation dumodle de donnes Axe 1
informations relatives aux livres. Lapplication de cette forme normale permet de
supprimer les inconsistances possibles entre les titres dun mme livre qui aurait t
command plusieurs fois, car le modle prcdent permettait davoir des valeurs de
Titre diffrentes pour une mme valeur de Livre.
Figure3.3
Modle physique
des donnes (MPD)
en deuxime forme
normale (2NF).
3.1.3 Troisime forme normale (3NF)
Pour qu'une entit soit en troisime forme normale (3NF), il faut:
qu'elle soit en deuxime forme normale (2NF);
que tous les attributs ne faisant pas partie de ses cls dpendent directement des cls
candidates.
la Figure3.3, lentit EnTeteCommandes nest pas en 3NF car toutes les infor-
mations relatives au client ne sont pas dpendantes de la commande. Il faut intro-
duire une nouvelle entit, qui contiendra les informations relatives aux clients.
Il devrait donc rester dans lentit EnTeteCommandes les attributs DateCommande
et MontantCommande. Mais est-ce que lattribut MontantCommande dpend direc-
tement de la cl? Apparemment oui, si on considre seulement lentit EnTeteCom-
mandes. Par contre, si on considre aussi ses associations, alors on saperoit que
cet attribut est en fait la somme des MontantLigne et ne dpend donc pas seulement
de la cl mais de lentit LignesCommandes. Cest ce quon appelle un "attribut
driv", cest une redondance dinformation. Pour tre en 3NF, il ne doit pas y avoir
dattributs drivs, il faut donc supprimer lattribut MontantCommande. Les attri-
buts calculs partir des colonnes de la mme entit sont eux aussi des attributs
drivs et ne sont pas admis dans la troisime forme normale.
On pourrait faire la mme remarque pour lattribut MontantLigne de lentit Lignes-
Commandes. Cependant, il y a un argument qui lautorise persister, cest que lat-
tribut MontantLigne est gal Quantit Prix du livre au moment de la commande,
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 3 Normalisation, base du modle relationnel 37
or, lattribut Prix de lentit CatalogueLivre est le prix actuel du livre. Ce prix est
susceptible de changer dans le temps, linformation de prix intgre dans lattribut
MontantLigne nest donc pas la mme information que le Prix de lentit Cata-
logueLivre. Ainsi, lattribut MontantLigne nest pas un attribut driv de lattribut
Prix de lentit CatalogueLivre (voir Section 3.2.1).
Figure3.4
Modle physique
des donnes (MPD)
en troisime forme
normale (3NF).
3.1.4 Forme normale de Boyce Codd (BCNF)
La forme normale de Boyce Codd est une version plus contraignante de la troisime
forme normale.
Pour qu'une entit soit en forme normale de Boyce Codd (BCNF), il faut:
qu'elle soit en troisime forme normale (3NF);
que tous les attributs ne faisant pas partie de ses cls dpendent exclusivement des
cls candidates.
la Figure3.4, lentit Clients nest pas en BCNF car lattribut Continent dpend
certes du client, mais il dpend aussi de lattribut Pays. Pour tre conformes, nous
devons crer une nouvelle entit permettant dassocier chaque Pays son Continent.
Figure3.5
Modle physique
des donnes (MPD)
en forme normale de
Boyce Codd (BCNF).
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
38 tude et optimisation dumodle de donnes Axe 1
3.1.5 Autres formes normales
Il existe dautres formes normales (quatrime, cinquime et sixime formes nor-
males). Cependant, elles sont un peu plus spcifques. Tendre vers une troisime
forme normale ou une forme normale de Boyce Codd est dj un excellent objectif.
3.2 Dnormalisation et ses cas de mise en uvre
La normalisation est une bonne intention quil est plus que souhaitable dappliquer.
Cependant, tout comme lenfer est pav de bonnes intentions, il faut savoir prendre
un peu de recul par rapport aux rgles afn de ne pas tomber dans certains excs. Si la
normalisation fournit de bons guides, je pense quil faut savoir les remettre en cause
sil y a de bonnes raisons de le faire. Le plus important est de se poser les bonnes
questions plutt que dappliquer aveuglment des rgles. Lobjet de cette section est
de donner quelques rgles pour ne pas respecter celles de la normalisation.
Nous abordons ici la notion de dnormalisation. C'est--dire que nous allons tudier comment
enfreindre certaines rgles sur un modle qui les applique.
Avant de dnormaliser un modle, il faut d'abord le normaliser.
3.2.1 La dnormalisation pour historisation
Cette premire forme de dnormalisation nen est pas vraiment une. Nous lavons
dj aborde, lors de ltude de la troisime forme normale avec lattribut Montant-
Ligne de lentit LignesCommandes.
Les formes normales ont pour objectif dviter la redondance de linformation. Si
on conoit le modle avec une vision statique, on risque de passer ct du fait
que certaines valeurs vont voluer dans le temps et quil ne sera plus possible de
retrouver aprs coup la valeur historique. Le prix courant dun article et le prix de ce
mme article il y a six mois ne sont pas forcment les mmes. Comme nous lavons
dj vu, il sagit de donnes distinctes. Mme si, certains instants, les valeurs sont
identiques, elles nont pas le mme cycle de vie.
La mthode la plus commune pour grer lhistorique dune valeur consiste reco-
pier linformation dans lentit qui lutilise. Une autre manire possible, et plus
ATTENTION
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 3 Normalisation, base du modle relationnel 39
conforme la logique des formes normales, pour grer ce besoin est de conserver
lhistorique de la donne rfrence dans une entit spare et horodate plutt que
de rpter la donne chaque instance la rfrenant.
Si nous reprenons lexemple du prix qui varie dans le temps, la premire mthode
possible consiste recopier le prix dans chaque ligne de commande (voir diagramme
de gauche la Figure3.6). On peut aussi crer une entit contenant lhistorique du
prix du livre. Ainsi, la donne prix nest pas rpte et on pourra tout moment la
retrouver partir de la date de la commande (voir diagramme de droite).
Figure3.6
Deux solutions possibles pour implmenter une gestion des commandes avec un historique
des prix.
Dans le cas prsent, mon cur balancerait plutt pour la premire solution (
gauche) car je sais quen termes dimplmentation la seconde solution ( droite) sera
plus complique. En effet, quand vous aurez besoin de connatre le prix dune ligne
de commande, vous devrez rechercher lenregistrement dhistorique le plus rcent
qui a une date antrieure la date de la commande. Cette requte-l nest dj pas
trs simple. Si on lajoute au fait quon souhaite calculer le montant total des com-
mandes dun client pour une anne, a devient alors complexe et peu performant
avec la seconde solution. La premire solution permet de rpondre cette requte
de faon assez intuitive et effcace. Dans dautres contextes, la seconde solution
pourrait prsenter plus davantages que la premire. Par exemple, si vous avez de
nombreux attributs garder en historique, quils soient volumineux (grands textes
descriptifs, photos, etc.) et voluent peu au regard des commandes. La seconde solu-
tion permet aussi de connatre les variations de prix dun produit mme si celui-ci
na pas t command entre les deux variations.
Comme toujours, il faut peser le pour et le contre de chaque solution plutt que
chercher forcment la solution mathmatiquement la plus juste.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
40 tude et optimisation dumodle de donnes Axe 1
Certains disent quil ne faut pas dnormaliser pour arranger le dveloppeur et quil
faut toujours choisir la solution la plus propre sous peine de se traner des "casse-
roles" pendant des annes. Cest gnralement vrai, cependant, comme le montre
lexemple prcdent, lapplication trop stricte de certaines rgles peut conduire
complexifer une application et avoir des impacts substantiels sur les performances.
Limportant est de se poser les bonnes questions et de faire vos choix en toute
honntet intellectuelle.
3.2.2 La dnormalisation pour performance et simplifcation
en environnement OLTP
La normalisation a pour but, entre autres, dviter la duplication de linformation
afn de renforcer la consistance des donnes. Cela peut avoir pour effet de nuire aux
performances. Comme nous lavons vu, le modle de droite de la Figure3.6 nest
pas adapt pour retrouver aisment lensemble des prix des lignes dune commande.
Ainsi, lorsque vous avez besoin daffcher sur une facture le montant total de la
commande, il faut faire une requte complique.
Imaginons un instant quil y ait une politique, variable pour chaque article, de
remises de prix en fonction de la quantit commande. Lajout dun champ Mon-
tantRemise pourrait tre considr comme un non-respect des formes normales car
il drive des attributs Quantit et CodeArticle. Cependant, je pense que, lorsquun
attribut est une valeur qui est drive de faon complexe, on peut raisonnablement
ne pas respecter la lettre la troisime forme normale.
Abordons prsent le cas des attributs drivs simples mais qui rendent service tels
que MontantLigne qui est gal QuantitPrix MontantRemise. On ne peut pas
dire que cela soit trs compliqu calculer, du coup ajouter cet attribut nest qu
moiti raisonnable. Une solution possible, et mon avis fdle lesprit des formes
normales, est dajouter une colonne virtuelle (ou calcule suivant le SGBDR),
laquelle contient le calcul et est maintenue par le SGBDR. Ainsi, il est sr que cette
information est consistante avec les informations dont elle drive. La limite de ce
type de champ est quil ne peut faire des calculs que sur les champs dune mme
table.
Regardons maintenant un autre cas dattributs drivs simples, des drivs par
agrgation, tels que lattribut MontantCommande qui est la somme des Montant-
Lignes la Figure 3.3. Sa prsence ne respecte pas la troisime forme normale,
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 3 Normalisation, base du modle relationnel 41
mais elle peut tre trs pratique pour calculer des indicateurs de chiffres daffaires
(CA) en temps rel. En plus dtre pratique, cela sera plus performant que de faire
la somme des lignes de chaque commande. Cependant, il faudra maintenir cette
valeur, donc faire rgulirement une requte qui recalcule la somme de Montant-
Lignes pour mettre jour lattribut MontantCommande. Cela peut tre acceptable
pour le cas de MontantCommande, mais il ne faut pas trop driver, sinon il y a un
risque de devoir calculer trop de donnes agrges chaque modifcation dune
donne.
En effet, afn de garantir la consistance de ces donnes, chaque fois que vous modi-
fez un enregistrement de LignesCommandes, vous devez recalculer les valeurs qui
en drivent. Par exemple, si vous navez pas t raisonnable, vous pourriez devoir
calculer toutes les valeurs suivantes : CA par jour, CA par mois, CA par jour par
Livre, CA par mois par Livre, CA par client par an, CA par mois par pays, CA
par mois par continent, etc. Vous risquez donc, si vous abusez de la dnormalisa-
tion, de plomber srieusement vos performances lors des mises jour des donnes
de votre base, alors que votre objectif tait damliorer les performances de votre
systme. Lutilisation de vues matrialises que nous tudierons au Chapitre5, sec-
tion 5.3.5, "Les vues matrialises", permet de maintenir ce genre de donnes de
faon consistante et relativement performante car les calculs sur ces objets sont faits
par variations et non pas par le recalcul complet des totaux (solution qui pourrait tre
extrmement coteuse).
Sur la plupart des SGBDR, vous pouvez implmenter des champs calculs l'aide de dclen-
cheurs (triggers). Certains SGBDR proposent aussi le concept de colonnes calcules qui sont,
contrairement aux dclencheurs, limites des calculs portant sur la table courante.
Sous SQL Server, vous disposez des colonnes calcules persistantes (stockes) ou non persis-
tantes (recalcules la vole) en utilisant la syntaxe suivante dans l'instruction CREATE TABLE.
ColCalculee as ColonneA+ColonneB PERSISTED
Sous Oracle, depuis la version11g, vous pouvez utiliser les colonnes virtuelles, qui ne sont
pas stockes, l'aide de la syntaxe suivante:
ColCalculee as (ColonneA+ColonneB)
Comme nous le verrons au Chapitre7, section7.4.1, "Impact des triggers", l'utilisation des
triggers, mme simples, peut entraner une chute des performances s'il y a beaucoup de LMD.
INFO
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
42 tude et optimisation dumodle de donnes Axe 1
3.2.3 La dnormalisation pour performance en environnement OLAP
On retrouve souvent les environnements OLAP (OnLine Analytical Processing)
sous les noms d"entrept de donnes" (datawarehouse) ou de "systme daide la
dcision" (DSS, Decision Support System). En environnement OLAP, la dnorma-
lisation est la rgle, car les formes normales ont t penses pour un environnement
OLTP. Lorsquon excute des requtes sur des centaines de milliers denregis-
trements, faire des jointures tout-va est assez coteux. Quand lessence mme
de votre base de donnes est de faire de lanalyse des donnes, cest du gchis de
passer son temps refaire les mmes jointures. Dans ce type de base de donnes, on
duplique plutt linformation afn de rduire le nombre de jointures et ainsi davoir
de meilleures performances.
La modlisation de bases OLAP quil nest pas prvu dtudier ici est une science
part entire et dpend un peu des outils mis disposition par votre moteur OLAP.
Cependant, les techniques doptimisation que nous allons aborder au cours de cet
ouvrage sont applicables aux bases OLAP.
Dans les bases OLAP, vous entendrez couramment parler de modle en toile et en
focons, de dimensions, de faits. SQL Server et Oracle intgrent des outils pour vous
aider manipuler ces concepts.
Je vous invite consulter dans la documentation de votre SGBDR les parties rela-
tives aux bases OLAP.
Figure3.7
Exemple de table
dnormalise pour
un usage OLAP.
En environnement OLAP, vous aurez tendance dupliquer dans les tables de faits
les donnes qui vous servent daxe danalyse. Le modle de donnes dune base
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 3 Normalisation, base du modle relationnel 43
OLAP sera construit en fonction des principaux types danalyses que vous prvoyez
de faire.
Dans lexemple de la Figure 3.7, nous voyons que nous allons pouvoir faire les
analyses suivantes:
par livre;
par commande;
gographique (Pays, Continent);
temporelle (Date de commande, Mois, Anne).
3.3 Notre base de test
Afn dillustrer les concepts que nous allons prsenter tout au long de ce livre,
nous allons les appliquer une base de test inspire des modles que nous venons
dtudier.
Cette base (structure et donnes) est disponible pour les SGBDR Oracle, SQL Server
et MySQL sur le site de lauteur ladresse http://www.altidev.com/livres.php.
Figure3.8
Modle physique des donnes de notre base de test.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
44 tude et optimisation dumodle de donnes Axe 1
Tableau3.1: Volumtrie de notre base de test
Nom table Nombre d'enregistrements
clients

45000
cmd 1 000000
cmd_lignes 2 606477
livres

2973
Nous illustrerons quelques mises en uvre avec deux autres bases de tests. La pre-
mire, bien connue dans le milieu Oracle, est la base emp/dept du schma SCOTT,
elle contient trs peu denregistrements.
Figure3.9
Modle physique des donnes de la base de test EMP.
Tableau3.2: Volumtrie de la base de test EMP
Nom table Nombre denregistrements
emp 14
dept 4
La seconde base de test est une volution de la prcdente qui contient plus den-
registrements (voir Annexe C pour plus de dtails) et intgre une table contenant
des augmentations appliquer aux employs. Elle sera utile pour tester les requtes
modifant les donnes.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 3 Normalisation, base du modle relationnel 45
Figure3.10
Modle physique des donnes de la base de test BIGEMP.
Tableau3.3: Volumtrie de la base de test BIGEMP
Nom table Nombre denregistrements
bigemp 1400014
bigdept

400004
augmentation 1400014
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Axe 2
tude et optimisation
desrequtes
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
4
Mthodes et outils de diagnostic
Avant de commencer optimiser une base de donnes, il est important de bien com-
prendre ce qui se passe et comment agit le SGBDR. Cette phase est fondamentale.
Loptimisation dune base de donnes ne se rsume pas juste appliquer quelques
recettes de cuisine sans rien comprendre ce que lon fait, ni limpact que chaque
action peut avoir.
4.1 Approche pour optimiser
Loptimisation dune base de donnes est une activit qui peut avoir lieu:
de faon curative, cest--dire lorsque les problmes apparaissent lors de limpl-
mentation ou en production;
de faon plus prventive lors de la conception de la base.
Afn que des problmes de performances ne surgissent pas durant la phase de pro-
duction, ce qui nuirait aux utilisateurs, il est important de les anticiper dans les
phases amont de la vie de lapplication. Pour cela, il faut intgrer la problmatique
des performances dans la dmarche de dveloppement comme toute autre exigence.
Cela signife, entre autres, quil faudra se donner les moyens dvaluer limpact de la
croissance du volume. Il nest pas facile, lorsque la base de donnes ne contient que
quelques centaines denregistrements, de mettre en vidence de futurs problmes de
performances. Il faut donc, en phase de dveloppement et/ou de test, travailler sur
une base qui se rapproche de ce que sera la ralit aprs quelques annes de produc-
tion. Cela peut se faire, en phase de maintenance, partir dune copie des donnes
des bases de production et, en phase de cration dune nouvelle application, en pro-
duisant des donnes factices laide de gnrateurs de donnes. Si un grand nombre
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
50 tude et optimisation desrequtes Axe 2
dutilisateurs est prvu, il sera pertinent de faire, en complment, des tests de charge
en simulant des utilisateurs simultans.
En phase de conception, vous naurez pas de retours des utilisateurs pour signaler
ce qui est lent et donc vous orienter vers les parties qui ont besoin dtre optimises.
Faut-il pour autant se creuser la tte sur toutes les tables de la base de donnes ?
Larponse est oui, pour ce qui est de la normalisation du modle de donnes, et non,
pour ce qui est des optimisations au niveau du SGBDR (index, etc.). Gnralement,
au moins 80% des donnes vont se concentrer dans moins de 20% des tables, cest
donc sur ces dernires quil va falloir concentrer vos efforts. De faon gnrale, une
table contenant moins dun millier denregistrements na pas besoin dtre optimise
(sauf cas particuliers).
Malgr vos efforts durant la phase de conception, il est possible que certaines
requtes souffrent de problmes de performances. Dans ce cas, il faudra appliquer
la mthode suivante:
1. valuer la situation au moyen de mesures et de lanalyse des schmas dexcution.
2. Appliquer une ou plusieurs solutions techniques.
3. valuer lamlioration.
Ce chapitre va vous aider traiter les points relatifs lvaluation. Les prochains
chapitres traiteront des solutions techniques possibles voques au deuxime point
de cette liste.
4.1.1 Mesurer
Comme la dit William Deming, "On ne peut amliorer que ce que lon mesure!"
En effet, si vous essayez diffrentes solutions pour amliorer une requte, comment
saurez-vous quelle est la meilleure solution si vous ne faites pas de mesures pour les
comparer? Il est ncessaire de trouver des critres tangibles valuer afn de mesurer
la progression apporte par les optimisations. Les principaux critres sont:
le temps de rponse;
la consommation mmoire;
la consommation CPU;
le nombre E/S (entres/sorties disque).
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 4 Mthodes et outils de diagnostic 51
La mesure synthtique la plus pratique est le temps dexcution. Cest un indicateur
assez simple dutilisation et cest, de plus, celui qui est ressenti par lutilisateur.
Ilfaut cependant excuter la requte plusieurs fois pour valider cette mesure, car le
niveau de charge global du systme et dautres lments infuent sur ce paramtre.
La plupart des environnements graphiques de dveloppement affchent systmati-
quement le temps dexcution de la dernire requte.
Sous Oracle SQL*Plus, il sactive avec la commande suivante:
set timing on;
Une autre solution, pour mesurer la consommation de ressources, consiste affcher
les statistiques relatives lexcution des requtes. la suite de chaque excution,
il est possible de rcuprer, dans les vues systme, les statistiques de la dernire
excution ainsi que le plan dexcution utilis. Attention, le plan dexcution utilis
affche des cots et des cardinalits estims et non les cots rels. Certains environ-
nements intgrent directement cette fonctionnalit, vous lactivez sur Oracle SQ
dvelopper, par exemple, travers licne (raccourci F10 Enregistrer la trace
automatique).
Dans lenvironnement Oracle SQL*Plus, on peut utiliser le mode AUTOTRACE
dont la syntaxe est la suivante:
SET AUTOT[RACE] {ON | OFF | TRACE[ONLY]} [EXP[LAIN]] [STAT[ISTICS]]
set autotrace on;
Loption ON implique les options explain et statistics :
explain affche le plan dexcution.
statistics affche les statistiques dexcution.
traceonly permet de ne pas affcher le rsultat lui-mme mais seulement les
informations relatives lexcution de la requte.
Lactivation du mode AUTOTRACE ncessite le rle PLUSTRACE, dfni dans le
script serveur @$ORACLE_HOME/sqlplus/admin/plustrce.sql :
grant PLUSTRACE to utilisateur;
Le mode AUTOTRACE ncessite la prsence dans le schma de lutilisateur de
la table plan_table qui est cre lors de lexcution du script serveur @$ORACLE_
HOME/rdbms/admin/utlxplan.sql.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
52 tude et optimisation desrequtes Axe 2
Ce mode peut aussi requrir laccs certaines vues de la mtabase:
grant select on V_$MYSTAT to utilisateur;
Ou de faon plus large:
grant select_catalog_role to utilisateur;
grant select any dictionary to utilisateur;
Listing4.1: Exemple de trace d'une excution sous SQL*Plus
SQL> set autotrace trace;
SQL> select * from cmd where noclient>30000;
848099 ligne(s) slectionne(s).
Plan d'excution
----------------------------------------------------------
Plan hash value: 2368838273
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 885K| 15M| 894 (2)| 00:00:11 |
|* 1 | TABLE ACCESS FULL| CMD | 885K| 15M| 894 (2)| 00:00:11 |
--------------------------------------------------------------------------
Predicate Information (identied by operation id):
---------------------------------------------------
1 - lter("NOCLIENT">30000)
Statistiques
----------------------------------------------------------
1 recursive calls
0 db block gets
59557 consistent gets
3142 physical reads
72 redo size
19938918 bytes sent via SQL*Net to client
622345 bytes received via SQL*Net from client
56541 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
848099 rows processed
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 4 Mthodes et outils de diagnostic 53
tudions de plus prs le rsultat obtenu:
En premier lieu, on obtient le nombre de lignes slectionnes.
Ensuite, on a le plan dexcution contenant les valeurs estimes et non pas les
effectives. Le plan est complt avec quelques statistiques relles de lexcution.
Enfn, se trouvent les statistiques suivantes:
Nom Description
consistent gets Nombre de blocs lus en mmoire aprs accs
ventuel au disque
physical reads Nombre de lectures effectives sur le disque
(exprim en blocs)
redo size Quantit de REDO ncessaire en octets
bytes sent via SQL*Net to client Octets envoys sur le rseau du serveur vers le
client
bytes received via SQL*Net from client Octets envoys sur le rseau du client vers le
serveur
SQL*Net roundtrips to/from client Nombre d'changes rseau entre le client et le
serveur
sorts (memory) Nombre de tris effectus compltement en
mmoire
sorts (disk) Nombre de tris ayant requis au moins un accs
disque
rows processed Nombre de lignes retournes
MS SQL Server
Dans l'environnement SQL Server Management Studio (SSMS), depuis une fentre
requte, l'quivalent du mode trace automatique est disponible par l'icne basculante
(Inclure le plan d'excution rel ou Ctrl+M). Ce mode affche, lors de chaque ex-
cution, le plan d'excution utilis avec quelques informations statistiques relles en plus
des informations estimes.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
54 tude et optimisation desrequtes Axe 2
MySQL
Pour tracer des instructions avec des statistiques depuis la version 5.0.37, vous pouvez
utiliser l'instruction SHOW PROFILE. Pour cela, vous devez commencer par activer le
profling avec l'instruction:
set proling=1;
puis, vous pouvez consulter les informations avec les instructions suivantes:
mysql> show proles\G
*************************** 1. row ***************************
Query_ID: 1
Duration: 0.02978425
Query: select max(nom) from clients where noclient>0
*************************** 2. row ***************************
Query_ID: 2
Duration: 0.02709625
Query: select max(nom) from clients where noclient<30000
mysql> show prole for query 2;
+--------------------+----------+
| Status | Duration |
+--------------------+----------+
| starting | 0.000102 |
| Opening tables | 0.000012 |
| System lock | 0.000004 |
| Table lock | 0.000006 |
| init | 0.000020 |
| optimizing | 0.000010 |
| statistics | 0.000034 |
| preparing | 0.000029 |
| executing | 0.000004 |
| Sending data | 0.026828 |
| end | 0.000006 |
| query end | 0.000004 |
| freeing items | 0.000033 |
| logging slow query | 0.000001 |
| cleaning up | 0.000005 |
+--------------------+----------+
Une autre solution consiste utiliser l'instruction SHOW STATUS qui affche environ 300sta-
tistiques sur la session en cours. Pour mesurer l'impact d'une requte, il sufft de purger
les statistiques avant d'excuter la requte l'aide de l'instruction:
Flush status;
puis d'affcher les statistiques en fltrant un groupe de statistiques avec l'instruction suivante:
mysql> show session status like 'Select%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| Select_full_join | 0 |
| Select_full_range_join | 0 |
| Select_range | 1 |
| Select_range_check | 0 |
| Select_scan | 0 |
+------------------------+-------+
Les groupes de statistiques les plus intressants sont Select, Handler, Sort, Created, Key
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 4 Mthodes et outils de diagnostic 55
4.1.2 Comprendre le plan d'excution
Le plan dexcution est lexpression par le SGBDR de la mthode daccs aux don-
nes pour rpondre une requte. Comme nous lavons vu au paragraphe prc-
dent, il saffche la suite de lexcution dune requte lorsque la trace automatique
est active. On peut aussi le consulter sans excuter la requte en passant par la
commande explain plan for puis en lanant le script @?/rdbms/admin/utlxpls.
sql. La plupart des outils de dveloppement pour Oracle, y compris loutil gratuit
Oracle SQL Developer, intgrent une interface permettant de le consulter.
Ci-aprs, la trace dexcution de la requte suivante:
select nom ,titre
from clients c join cmd on c.noclient=cmd.noclient
join cmd_lignes cl on cl.nocmd=cmd.nocmd
join livres l on cl.nolivre=l.nolivre
where C.pays='France' and L.editeur='Pearson';
Listing4.2: Plan d'excution avec SQL*Plus
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 572 | 47476 | 2975 (2)| 00:00:36 |
|* 1 | HASH JOIN | | 572 | 47476 | 2975 (2)| 00:00:36 |
|* 2 | TABLE ACCESS FULL | LIVRES | 35 | 1470 | 13 (0)| 00:00:01 |
|* 3 | HASH JOIN | | 48490 | 1941K| 2961 (2)| 00:00:36 |
|* 4 | HASH JOIN | | 18613 | 563K| 1066 (2)| 00:00:13 |
|* 5 | TABLE ACCESS FULL | CLIENTS | 841 | 16820 | 171 (1)| 00:00:03 |
| 6 | TABLE ACCESS FULL | CMD | 1000K| 10M| 890 (2)| 00:00:11 |
| 7 | INDEX FAST FULL SCAN| PK_CMD_LIGNES | 2606K| 24M| 1883 (1)| 00:00:23 |
-------------------------------------------------------------------------------------
Predicate Information (identied by operation id):
---------------------------------------------------
1 - access("CL"."NOLIVRE"="L"."NOLIVRE")
2 - lter("L"."EDITEUR"='Pearson')
3 - access("CL"."NOCMD"="CMD"."NOCMD")
4 - access("C"."NOCLIENT"="CMD"."NOCLIENT")
5 - lter("C"."PAYS"='France')

Le plan dexcution prsente la liste des oprations qui vont tre effectues lors de
lexcution, reste comprendre ce que cela veut dire. Nous allons voir ci-aprs les
oprations les plus frquemment rencontres.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
56 tude et optimisation desrequtes Axe 2
Figure4.1
Plan d'excution sous
Oracle SQL*Developer.
Il contient les mmes
informations que sous
SQL*Plus mais prsentes
diffremment.
Il en existe dautres, plus "exotiques", souvent lies une fonction en particu-
lier, consultez la documentation Oracle pour plus dinformation. Mais dcodons
dabord le plan dexcution de la Figure4.1:
1. Parcours complet de la table clients en fltrant PAYS='France'.
2. Jointure de type HASH JOIN par la colonne Noclient entre le rsultat de lopration
prcdente et la table cmd via un parcours complet de la table cmd.
3. Jointure de type HASH JOIN par la colonne Nocmd entre le rsultat de lop-
ration prcdente et la table cmd_lignes via lindex PK_CMD_LIGNES (la table
cmd_lignes napparat pas directement car seules les colonnes Nocmd et
Nolivre prsentes dans lindex sont ncessaires).
4. Parcours complet de la table livres en fltrant EDITEUR='Pearson'.
5. Jointure de type HASH JOIN par la colonne Nolivre entre le rsultat de lopration
prcdente et le rsultat de lopration3.
Le plan dexcution se lit du fond de larbre vers la racine. La colonne Cardinality
contient lestimation du nombre de lignes manipules par lopration.
Oprations d'accs aux tables
Full Table Scan. Cette opration est assez simple comprendre: la table est parcou-
rue (scanne) entirement, de faon linaire, dans lordre le plus simple, cest--dire
lordre des blocs dans le tablespace.
Partition. Opration effectue sur des partitions et non sur la table entire, spci-
fque de la manipulation de tables partitionnes.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 4 Mthodes et outils de diagnostic 57
Table Access By RowID. Cette opration permet un accs direct un enregistre-
ment au sein dun bloc de donnes grce au RowID qui contient ladresse du bloc
et loffset de la ligne dans le bloc. Cela a gnralement lieu aprs laccs un index
qui fournit le RowID. Cette opration est aussi effectue sur une condition du type
rowid= AAARdSAAGAAAGg0AAA.
Oprations d'accs aux index
Unique Scan. Parcourt larborescence de lindex pour localiser une cl unique.
Typiquement utilis sur une condition du type noclient=37569.
Range Scan. Parcourt une partie dindex de faon ordonne. Typiquement utilis
sur une condition du type noclient between 50000 and 60000.
Full Scan. Parcourt un index en entier en respectant lordre de lindex.
Fast Full Scan. Analogue Full Scan mais ne respecte pas lordre des donnes.
Typiquement utilis lorsquune condition peut tre applique sur un index sans que
lordre de tri soit mis en jeu. Par exemple:
select count(*) from clients where mod(noclient, 1000) = 150.
Skip Scan. Utilise les index multicolonnes sans tenir compte des premires colonnes.
Dans ce cas, lindex est considr comme un ensemble de sous-index.
Bitmap. Utilise un index de type bitmap.
Partition. Utilise un index partitionn.
Oprations de jointure
Nested Loop (boucles imbriques). Parcourt les sous-ensembles pour chaque
valeur de lensemble de donnes pilotes.
Illustrons ce comportement avec la requte suivante:
select * from cmd
where noclient in (select noclient from clients
where pays='Cameroun' )
La sous-requte va tre lensemble pilote en ramenant une liste de 30clients. Pour
chacun de ces Noclient, le SGBDR va excuter la requte principale. Cela quivaut
au pseudo-code suivant:
Foreach NoDuClientPilote in (select noclient from clients
where pays='Cameroun')
select * from cmd where noclient = NoDuClientPilote
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
58 tude et optimisation desrequtes Axe 2
Merge Join. Rapproche deux ensembles de donnes tris. Le principe est que deux
curseurs parcourent linairement les ensembles tris. Cette solution est performante
pour rapprocher deux ensembles dj tris sur les cls de jointure (voir Figure 4.2).
Figure4.2
Illustration
d'un Merge Join par
les champs N CMD.
N CMD
14524
14525
14526
14527
14528
14529
14530
14531
14532
14533
14534
14535
14536
14537
14538
14539
14540
14541
14542
N CLIENT
106141
131869
83068
120877
34288
103897
63544
92173
18994
22006
46777
103180
56563
107179
102964
77719
121630
44011
81100
DATECOMMANDE
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
N CMD
14524
14524
14525
14525
14526
14526
14527
14527
14528
14528
14528
14528
14528
14529
14529
14530
14530
14531
14531
N LIVRE
6187
7789
4234
5554
5080
1579
4447
4396
4237
5380
2257
4339
4660
4651
5419
4177
7426
7423
8308
QUANTITE
1
1
3
3
3
3
1
4
8
5
6
7
7
1
1
1
4
2
3
Hash Join. Construit une table de hachage permettant daccder plus rapidement
aux cls (voir Figure 4.3).
1
Construction
table hachage

Recherche des valeurs
dans table hachage
3
Comparaison entre
les enregistrements
ayant le mme hash code
Table ou index A Table ou index B
NCLIENT
14581
14584
14587
14590
14593
14596
14599
14602
14605
14608
14611
14614
NOM
Richards
Farrow
Reeves
Kidman
Palin
Molina
Swinton
Ricci
Damon
Rio
Blades
Bacon
PRENOM
Keith
Talvin
Heather
Xander
Jonatha
Sheryl
Lynn
Tracy
Gladys
Jon
Johnnie
Trini
NCMD
14524
14525
14526
14527
14528
14529
14530
14531
14532
14533
14534
14535
14536
14537
14538
14539
14540
14541
14542
NCLIENT
106141
131869
83068
120877
34288
103897
63544
92173
18994
22006
46777
103180
56563
107179
102964
77719
121630
44011
81100
DATECOMMANDE
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
16/04/2004
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
A11
A12
A13
A14
A15
A16
A17
A18
A19
A20
A21
A22
A23
A24
A25
B1
B2
B3
B4
B5
B6
B7
B8
B9
B10
B11
B12
B13
B14
B15
B16
B17
B18
B19
B20
B21
B22
B23
B24
B25
C1
C2
C3
C4
C5
C6
C7
C8
C9
C10
C11
C12
C13
C14
C15
C16
C17
C18
C19
C20
C21
C22
C23
C24
C25
D1
D2
D3
D4
D5
D6
D7
D8
D9
D10
D11
D12
D13
D14
D15
D16
D17
D18
D19
D20
D21
D22
D23
D24
D25
E1
E2
E3
E4
E5
E6
E7
E8
E9
E10
E11
E12
E13
E14
E15
E16
E17
E18
E19
E20
E21
E22
E23
E24
E25
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
F13
F14
F15
F16
F17
F18
F19
F20
F21
F22
F23
F24
F25
G1
G2
G3
G4
G5
G6
G7
G8
G9
G10
G11
G12
G13
G14
G15
G16
G17
G18
G19
G20
G21
G22
G23
G24
G25
H1
H2
H3
H4
H5
H6
H7
H8
H9
H10
H11
H12
H13
H14
H15
H16
H17
H18
H19
H20
H21
H22
H23
H24
H25
2
Figure4.3
Exemple Hash Join de la forme clients.noclient=cmd.noclient.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 4 Mthodes et outils de diagnostic 59
1. On parcourt la table A (clients) car cest celle qui a le moins denregistre-
ments. Avec une fonction de hachage, on calcule le hashcode de chaque cl de
la jointure pour construire une table de hachage (hash table).
2. On parcourt la table B (cmd) et, pour chaque valeur de la cl de jointure, on
cherche si son hashcode existe dans la table de hachage (sil nexiste pas, cest
que cette ligne na pas de correspondance dans lautre table).
3. Si on a trouv une correspondance, on teste pour chaque enregistrement de la
tableA correspondant au hashcode si la cl est gale la cl de la tableB.
Une fonction de hachage (qui donne le hashcode) est une fonction injective qui
donnera toujours le mme rsultat pour une valeur donne, mais plusieurs valeurs
dentres pourront donner la mme valeur de sortie. Le but de la table de hachage
est de crer une liste de valeurs ordonne et continue, qui permettra de regrouper
des petits ensembles de donnes dans chacune de ses cases. Il suffra de comparer
chaque cl avec seulement le sous-ensemble des cls qui a le mme hashcode et non
pas avec toutes les cls.
Idalement, petit ensemble signifera infrieur ou gal un enregistrement (par-
fois0, souvent1, parfois plus). Ce souhait impliquera davoir une table de hachage
la plus grande possible.
Le but de cette technique est de ne comparer chaque enregistrement de la tableB
qu peu denregistrements de la tableA. Cette dernire sera forcment la plus petite
afn de respecter lobjectif davoir le moins denregistrements correspondants une
case de la table de hachage.
Outer Join (jointure externe). Ce sont des variantes des jointures prcdentes.
Elles suivent le mme principe, si ce nest quon slectionne aussi les lignes qui
nont pas de correspondance.
Autres oprations
Union, Intersection, Minus. Effectuent des oprations ensemblistes. Cest gnra-
lement explicite dans la requte.
Sort. Effectue un tri.
Sort Agregate. Effectue une opration dagrgation (SUM, AVG, COUNT, etc.).
Filter. Filtre des donnes suivant un prdicat (synonyme de condition).
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
60 tude et optimisation desrequtes Axe 2
MS SQL Server
Dans l'environnement SQL Server Management Studio (SSMS), depuis une fentre re-
qute, vous pouvez utiliser l'icne (Affcher le plan d'excution estim ou Ctrl+L)
pour affcher le plan d'excution (voir Figure4.4). La zone d'information jaune dtaillant
l'opration apparat si l'on passe le curseur sur une des oprations.
Figure4.4
Plan d'excution
SQL Server.
Les oprations ne sont pas les mmes que sous Oracle, mais on retrouve les mmes prin-
cipes.
MySQL
Dans l'outil MySQL Query Browser, vous pouvez cliquer sur l'icne Explain pour affcher
le plan d'excution (voir Figure4.5).
Figure4.5
Plan d'excution
MySQL.
Le plan s'affche dans la zone du bas. Si vous travaillez en ligne de commande, vous
pouvez utiliser EXPLAIN ou EXPLAIN EXTENDED comme illustr ci-aprs. L'utilisation de \G
permet d'avoir une prsentation verticale plus pratique lire.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 4 Mthodes et outils de diagnostic 61
mysql> EXPLAIN EXTENDED select * from clients where noclient<30000 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: clients
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: NULL
rows: 5275
ltered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
4.1.3 Identifer les requtes qui posent des problmes
Avant de travailler rsoudre les problmes, il faut correctement les identifer. En
premier lieu, il faut identifer les requtes qui posent le plus de problmes et se
concentrer sur celles-ci.
Diffrentes mthodes existent pour trouver les requtes optimiser.
Utilisation de V$SQL
Une premire manire, qui est la plus basique, consiste utiliser la vue dynamique
v$sql qui contient les requtes excutes rcemment ainsi que des informations
statistiques sur leur excution. Je vous conseille de mettre des limites pour ne cibler
que votre schma et exclure les requtes internes dOracle (Dans l'exemple ci-des-
sous, la valeur SCOTT doit tre remplace par votre nom de schma).
SELECT * from V$SQL t
where LAST_active_TIME is not null
and t.PARSING_SCHEMA_NAME ='SCOTT'
and upper(t.SQL_TEXT) not like '%SYS.%' and upper(t.SQL_TEXT) not like '%V$%'
and upper(t.SQL_TEXT) not like 'EXPLAIN %'
order by t.LAST_active_TIME desc
On pourra ajouter des conditions sur des noms de tables mises en jeu, comme dans
la condition ci-aprs, pour rduire encore le volume des requtes retournes.
and upper(t.SQL_TEXT) like '%CMD%'

Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
62 tude et optimisation desrequtes Axe 2
Les colonnes de cette requte les plus intressantes sont les suivantes:
Fetches, Executions. Elles aident reprer les requtes ramenant beaucoup de
lignes et celles excutes frquemment. Les deux sont importantes: en effet, une
petite requte ayant un mauvais temps de rponse peut devenir pnalisante si elle
est excute des milliers de fois.
Disk read, Buffer gets. Elles aident trouver les requtes qui ncessitent de
manipuler beaucoup de donnes dans la base, mme si elles nen ramnent que
trs peu.
Sql_text, Full text. Elles contiennent le texte des requtes qui ont t slectionnes
grce aux champs prcdemment dcrits.
Laccs la vue v$sql peut ncessiter les privilges suivants:
grant select_catalog_role to utilisateur;
grant select any dictionary to utilisateur;
Statistiques au niveau de l'instance
Une autre mthode sappuie sur les outils Statspack ou AWR (Automatic Workload
Repository) qui se servent des statistiques au niveau de linstance. Cela dit, sur un
serveur trs actif qui fait tourner de nombreuses applications, vous ne trouverez peut-
tre pas dinformations pour vous aider en rapport avec une application particulire.
Le Statspack est un outil en fn de vie qui a pour but de collecter des statistiques au
niveau de linstance et, par la suite, den extraire des rapports.
Mode demploi rapide:
1. Si ce nest dj fait, installez-le en excutant sur le serveur le script rdbms/
admin/spcreate.sql.
2. Prenez des snapshots en excutant:
exec statspack.snap;
3. Dans Oracle SQL*Plus, excutez le script spreport.sql qui va gnrer des
fchiers rsultats dans le rpertoire de travail de SQL*Plus.
AWR est le remplaant du Statspack, il donne des informations trs proches de
celles du Statspack, en plus complet. Parfaitement intgr la console dadminis-
tration OEM (Oracle Enterprise Manager), il est install automatiquement sur une
installation standard. Par dfaut, il prend un clich (snapshot) toutes les heures.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 4 Mthodes et outils de diagnostic 63
Les fonctions relatives AWR sont disponibles dans la console dadministration web,
dans la partie relative linstance, onglet Serveur, cadre Gestion des statistiques, lien
Rfrentiel de charge globale automatique. Sur cet cran, vous pouvez visualiser les
clichs disponibles et excuter un rapport AWR entre deux clichs de votre choix.
Les rapports permettent de visualiser des statistiques sur le niveau de charge ainsi
que les vnements les plus signifcatifs, parmi lesquels les instructions SQL les
plus consommatrices de CPU, dE/S ou les plus frquentes. Suite lexcution
dun rapport AWR, vous pouvez excuter ADDM (Automatic Database Diagnostic
Monitor) qui fera des propositions dactions fondes sur les informations les plus
pertinentes du rapport AWR. Dans certains cas, il peut proposer dexcuter SQL
Tuning Advisor (voir section4.2.2 de ce mme chapitre) afn de faire des propositions
damlioration du SQL.
Suivi des performances de la console web
Une troisime mthode consiste utiliser longlet performance de la base de don-
nes. Cet cran permet de visualiser les taux dactivit les plus levs en temps rel
ainsi que didentifer les sessions et les instructions ayant le taux dactivit le plus
lev au moyen du lien "Taux dactivit les plus levs".
Figure4.6
cran de la console d'administration montrant les taux d'activit les plus levs.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
64 tude et optimisation desrequtes Axe 2
Dans la console, de nombreux crans peuvent vous aider trouver les requtes,
applications ou utilisateurs, qui consomment le plus de ressources. Ces crans mritent
dtre tudis attentivement.
Trace des requtes
Une quatrime manire consiste tracer lexcution de toutes les requtes:
Soit, si cela est possible, en traant les excutions ct application cliente laide
des outils de monitoring ct client afn dtudier cran par cran le trafc gnr
et le temps de rponse de chacune des requtes. Cette approche est conditionne
la disponibilit de tels outils pour votre environnement de dveloppement.
Soit, en traant des requtes ct serveur, en utilisant loutil SQL Trace, dtaill
la section4.2.4 de ce chapitre.
4.2 Outils complmentaires
4.2.1 Compteurs de performance Windows
Sous Windows, il est facile daccder un ensemble de paramtres permettant dai-
der au diagnostic lors dune chute de performance. Ces donnes sont consultables au
moyen des compteurs de performance visualisables au travers du moniteur de per-
formance (il existe des choses plus ou moins analogues sur les autres plates-formes).
Cet outil vous permettra de surveiller lusage des ressources matrielles de votre
serveur. Les compteurs les plus importants sont:
% processeur. Affche le taux dusage du CPU. Si lensemble des CPU tend
vers 100%, cela signife que les processeurs ont atteint leur limite de traitement.
Pages/s. Indique le niveau dchange entre la mmoire virtuelle et la mmoire
physique. Si ce compteur prsente en permanence des valeurs leves, cela
signife que le systme manque de mmoire physique ou que les applications en
demandent trop.
Octets lus et crits/seconde. Montre le niveau de sollicitation du sous-systme
disque.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 4 Mthodes et outils de diagnostic 65
Mmoire disponible. Permet de vous assurer que le serveur dispose encore dun
peu dair. Gnralement, si la mmoire vive passe sous la barre des 100Mo, cela
signife quelle est sature.
Cet outil permet de travailler au niveau serveur, il ne vous aidera pas dans le dia-
gnostic dune requte mais pour mettre en vidence une saturation au niveau du
matriel. Cette saturation peut indiquer que le matriel atteint ses limites, mais les
limites elles-mmes peuvent tre atteintes parce quil y a un problme en amont
(base mal confgure, requtes peu performantes).
MS SQL Server
De trs nombreux compteurs de performances SQL Server sont disponibles. Ils permettent
de se faire une bonne ide de l'activit de chaque instance de SQL Server.
4.2.2 SQL Tuning Advisor (Oracle)
Ce module, quon pourrait traduire par "Assistant doptimisation SQL", permet
danalyser une requte et den dgager des propositions damlioration. Il est acces-
sible depuis la console web, soit depuis la feuille de calcul SQL, soit depuis les
crans de suivi de la performance. Si nous soumettons la requte ci-aprs, nous
obtenons les recommandations de la Figure4.7:
select * from clients where codepostal='40321'
Figure4.7
Recommandations sur une requte.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
66 tude et optimisation desrequtes Axe 2
SQL Tuning Advisor propose de visualiser le plan dexcution que cela donnerait
en appliquant les recommandations au moyen des icnes de visualisation prsentes
dans les colonnes Nouveaux dtails du plan dexcution et Comparer les plans
dexcution (voir Figure4.8). Le bouton Implmenter permet de crer directement
lindex recommand.
Cette fonction peut tre utile, mais elle reste cependant relativement limite et ne
propose quune partie des optimisations possibles.
Figure4.8
cran de comparaison des plans d'excution.
4.2.3 SQL Access Advisor (Oracle)
Cette fonction de conseil prsente des similitudes avec SQL Tuning Advisor. La
principale diffrence est quelle travaille sur un ensemble de requtes pour proposer
ses conseils, alors que SQL Tuning Advisor travaille sur une seule requte la fois.
SQL Access Advisor prend en compte le nombre dexcutions de chaque requte.
Vous accdez cette fonction par le Centre de Conseil, en choisissant Fonctions de
conseil SQL puis SQL Access Advisor.
INFO
Il est possible que vous rencontriez quelques diffcults excuter une tche SQL Access
Advisor. Cela peut venir du fait que vous utilisez un navigateur sur un poste de travail en
franais sur une base qui est confgure en anglais (voir avec l'instruction ci-aprs).
show parameter nls_language
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 4 Mthodes et outils de diagnostic 67
Si c'est le cas, un workaround rfrenc consiste effectuer l'opration suivante dans votre
navigateur (ici expliqu avec Internet Explorer). Dans le menu Outils > Options Internet, cli-
quez sur Langues, ajoutez la langue "Anglais (tats unis)" et passez-la en premire position.
Cela aura pour effet de passer les crans de la console en langue anglaise mais vous permet-
tra de mener terme l'excution de SQL Access Advisor.
Dans les conseils obtenus de SQL Access Advisor, il se peut que vous vous demandiez quoi
correspond l'action RETAIN INDEX qui suggre le code SQL suivant:
/* RETAIN INDEX "UnOwner"."UnIndex" */
Sachez que c'est juste une confrmation de la part de SQL Access Advisor qui estime que
votre index est utile et que vous devriez le garder. Ce code SQL est seulement un commen-
taire, et rien de plus.
4.2.4 SQL Trace (Oracle)
SQL Trace est la mthode historique permettant de tracer lactivit dune base de
donnes. Ce nest plus la plus recommande par Oracle qui, prsent, conseille plu-
tt dutiliser la console web. Consquence, cette fonction a trs peu volu depuis
plusieurs versions dOracle et nest de ce fait, pas trs pratique mettre en uvre.
Gnrer les traces
Il est possible dactiver la fonction de trace du SQL avec un fltrage aux niveaux
suivants:
instance;
session utilisateur;
identifant client;
service, module, action.
Les traces sont places dans des fchiers stocks sur le serveur dans le rpertoire
dsign par le paramtre UDUMP, dont vous pouvez consulter la valeur laide de
linstruction suivante:
SHOW PARAMETERS user_dump_dest;
Vous pouvez modifer ce paramtre laide de linstruction:
ALTER SYSTEM SET user_dump_dest = '/nouveau_repertoire_user_dump' SCOPE=both;
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
68 tude et optimisation desrequtes Axe 2
Pour avoir des informations plus compltes dans les fchiers de trace, il faut sassu-
rer que le paramtre timed_statistics est true et, le cas chant, le modifer (par
dfaut, il est false) laide des instructions suivantes:
SHOW PARAMETERS timed_statistics;
ALTER SYSTEM SET timed_statistics = true SCOPE=memory;
Pour activer la trace au niveau instance, vous pouvez excuter une des instructions
suivantes:
ALTER SYSTEM SET sql_trace = true SCOPE=MEMORY;
EXECUTE DBMS_MONITOR.DATABASE_TRACE_ENABLE(waits => TRUE, binds => FALSE,
instance_name => 'orcl');
Pour dsactiver la trace au niveau instance, vous pouvez excuter une des instructions
suivantes:
ALTER SYSTEM SET sql_trace = false SCOPE=MEMORY;
EXECUTE DBMS_MONITOR.DATABASE_TRACE_DISABLE(instance_name => 'orcl');
Pour les autres niveaux de fltrage (session, identifant client, service, module, action),
vous aurez besoin dinformations complmentaires que vous pourrez consulter dans
la vue v$sessions laide de la requte suivante:
select sid,serial#,username,module,action,service_name,client_identier
from V$SESSION
Vous pouvez infuer sur la valeur client_identier depuis lapplication en utilisant
la fonction PL/SQL suivante:
dbms_session.set_identier('VotreIdentiant');
Pour infuer sur les valeurs de module et action depuis votre application, vous pouvez
utiliser les procdures suivantes du package DBMS_APPLICATION_INFO:
DBMS_APPLICATION_INFO.SET_MODULE (module_name, action_name);
DBMS_APPLICATION_INFO.SET_ACTION (action_name);
Pour activer la trace sur la session courante, vous pouvez utiliser les instructions sui-
vantes qui activent la trace et, optionnellement, y affectent un identifant permettant
de retrouver le fchier de trace plus facilement:
ALTER SESSION SET sql_trace = true;
ALTER SESSION SET tracele_identier = matrace25;
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 4 Mthodes et outils de diagnostic 69
Pour stopper la trace:
ALTER SESSION SET sql_trace = false;
Attention, cette instruction requiert le privilge ALTER SESSION qui nest pas donn
par dfaut aux utilisateurs. Oracle recommande dailleurs de ne pas laccorder
systmatiquement et de faon permanente.
Vous pouvez activer la trace dune autre session partir dune des instructions
suivantes en utilisant les informations de la vue v$sessions en paramtres:
execute dbms_system.set_sql_trace_in_session(142, 1270, true);
execute dbms_monitor.session_trace_enable(session_id => 142, serial_num
=> 1270, waits => true, binds => false);
Pour stopper la trace, excutez une de ces instructions:
execute dbms_system.set_sql_trace_in_session(142, 1270, false);
execute dbms_monitor.session_trace_disable(session_id => 142, serial_num
=> 1270);
Pour activer et dsactiver les traces SQL avec dautres niveaux de fltrage, choisissez
parmi les procdures suivantes du package DBMS_MONITOR :
CLIENT_ID_TRACE_ENABLE( client_id, waits, binds, plan_stat);
CLIENT_ID_TRACE_DISABLE( client_id);
SERV_MOD_ACT_TRACE_ENABLE(service_name, module_name, action_name,
waits, binds ,instance_name, plan_stat);
SERV_MOD_ACT_TRACE_DISABLE(service_name, module_name, action_name,
instance_name);.
Analyser les traces avec tkprof
Nous venons de voir comment capturer des donnes dans des fchiers de trace.
prsent, nous allons voir les moyens permettant de les consulter.
La premire chose faire sera didentifer votre fchier de trace dans le rpertoire
contenant toutes les traces, laide de lheure par exemple. Linstruction ALTER SES-
SION tracele_identier tudie prcdemment pourra vous y aider.
Ensuite, lutilitaire tkprof vous permettra de convertir ce fchier de trace binaire
(.trc) en fchier texte (.txt) lisible. Linstruction ci-aprs traite cette conversion:
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
70 tude et optimisation desrequtes Axe 2
tkprof orcl_ora_2052_MATRACE25.trc orcl_ora_2052_MATRACE25.txt
Dans le fchier texte gnr, vous trouverez les informations suivantes pour chaque
requte:
SQL ID : 5x7w56mw30q9x
select count(*) from cmd_lignes where nolivre=6262 and remise=7
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.06 6.00 8286 8291 0 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.06 6.00 8286 8291 0 1
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 81
Rows Row Source Operation
------- ---------------------------------------------------
1 SORT AGGREGATE (cr=8291 pr=8286 pw=8286 time=0 us)
281 TABLE ACCESS FULL CMD_LIGNES (cr=8291 pr=8286 pw=8286 time=50914 us
cost=2317 size=1470 card=210)
********************************************************************************
Par dfaut, si une requte est excute plusieurs fois, elle sera consolide et nap-
paratra quune seule fois dans le fchier rsultat. Le premier tableau de statistiques
indiquera combien de fois chaque requte a t excute. Si vous avez activ les
statistiques, vous aurez le dtail de chaque opration du plan avec les statistiques (cr
= Consistent Read Mode, pr = Buffer Gets).
Loption tkprof explain permet de rinterroger la base pour obtenir le plan dex-
cution de votre requte. Attention, ce nest pas forcment celui qui tait utilis au
moment de la trace.
Loption tkprof sys=no permet de ne pas traiter les requtes rcursives effectues
par le SGBDR.
Lutilitaire trcsess permet dagrger dans un mme fchier le rsultat de plusieurs
fchiers de trace en fonction du numro de session, client id, service, module, action
en vue de les traiter avec tkprof.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 4 Mthodes et outils de diagnostic 71
Analyser les traces avec Trace Analyzer
Trace Analyzer, disponible sur Oracle MetaLink dans la note 224270.1, est un uti-
litaire analogue tkprof qui donne un rapport au format HTML plus pratique
exploiter. Il fournit une synthse des instructions les plus consommatrices et, pour
chaque instruction, des informations dans une mise en forme agrable. Reportez-
vous sa documentation pour linstaller.
Pour lutiliser depuis SQL*Plus connect avec le compte qui a servi faire la trace,
excutez le script trcanlzr.sql avec votre fchier de trace en paramtre.
@D:\Ora\product\11.1.0\db_1\trca\run\trcanlzr.sql orcl_ora_2052_MATRACE25.trc
Ce script gnre un fchier zip qui contient le rapport en format HTML (voir Figure 4.9).
Consultez le rpertoire Doc de Trace Analyzer pour avoir plus dinformations et des
explications qui vous aideront analyser les rapports.
Figure4.9
Dtail d'une requte
dans le rapport gnr
par Trace Analyzer.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
72 tude et optimisation desrequtes Axe 2
4.2.5 Outils SQL Server
SQL Server propose aussi des outils pour aider au diagnostic. Lquivalent de
loutil de trace est SQL Server Profler qui permet de capturer le trafc SQL dun
serveur.
Figure4.10
cran de SQL Server Profler.
Lquivalent de la fonction de conseil Oracle SQL Access Advisor est disponible via
lassistant de paramtrage du serveur (Database Engine Tuning Advisor).
Figure4.11
cran de l'assistant de paramtrage du serveur.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 4 Mthodes et outils de diagnostic 73
4.2.6 Outils MySQL
Sous MySQL, les outils disponibles sont un peu moins nombreux, du moins dans
la version communautaire. La version Enterprise propose dans ses variantes les
plus volues un outil de monitoring du serveur. Celui-ci, plutt orient production,
intgre cependant Query Analyzer, un outil qui permet de suivre les requtes occupant
le plus de ressources.
Figure4.12
cran du Query Analyzer.
En cliquant sur une requte, vous pourrez accder quelques statistiques et au plan
dexcution. Attention, le Query Analyzer passe par un proxy pour capturer les
requtes. Vous devez donc rediriger le fux de requte sur le port du proxy qui les
enverra vers le serveur.
Si vous ne possdez pas une version Entreprise, il vous reste quand mme quelques
solutions pour savoir quelles requtes optimiser. Vous pouvez activer la journali-
sation de toutes les requtes avec le paramtre log. Ce mode de journalisation ne
donne aucune indication relative au temps dexcution, il permet juste de reprer les
requtes les plus excutes.
Le paramtre log_slow_queries permet dactiver la journalisation des requtes les
plus lentes. Ce sont celles qui durent plus de long_query_time secondes ou qui
nutilisent pas dindex si log-queries-not-using-indexes est activ. long_query_
time est exprim en secondes et ne peut pas tre infrieur une seconde. Vous ne
pourrez ainsi pas confgurer de tracer les requtes de plus de 0,2seconde quil serait
peut tre pertinent danalyser.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
74 tude et optimisation desrequtes Axe 2
Le fchier journal des requtes lentes est plus complet que le log gnral des requtes,
voici un exemple dune entre:
# Time: 100219 10:44:18
# User@Host: root[root] @ localhost [127.0.0.1]
# Query_time: 25.421875 Lock_time: 0.000000 Rows_sent: 4026540 Rows_
examined: 140
SET timestamp=1266572658;
select c.* from clients c,clients c2 where c.adresse1 like '%A%' and c2.
noclient<15000;
On y trouve le texte de la requte ainsi que le temps dexcution.
Si vous souhaitez tracer plus de requtes, vous pouvez vous inspirer de la logique
du Query Analyzer en utilisant le serveur proxy MySQL disponible sur http://dev.
mysql.com/downloads/.
Vous devrez le confgurer pour quil trace les requtes qui vous intressent. Ce ser-
veur de proxy peut excuter du code LUA pour chaque requte qui transite tra-
vers lui. Le rpertoire share\doc\mysql-proxy contient des exemples de scripts qui
pourront vous aider et plus particulirement le fchier analyze-query.lua. En vous
documentant un peu, vous pourrez apporter quelques modifcations ce script en
remplaant par exemple les affchages par une criture dans un fchier laide des
instructions suivantes:
-- Dclaration au dbut du chier
local logger = io.open("querylog.txt", "a+")
-- la place de print(o)
logger:write(o)
logger:ush()
Adaptez les valeurs de proxy.global.cong.analyze_query et, ventuellement,
modifez la condition qui prcde la journalisation par if o then si vous ne souhaitez
rien fltrer.
Dans le fchier de confguration du proxy, ajoutez cette instruction pour prendre en
compte ce script:
proxy-lua-script = share\\doc\\mysql-proxy\\VotreAnalyze-query.lua
Une fois que vous aurez adapt ces scripts, vous pourrez obtenir pour chaque requte
les informations ci-aprs, quil ne vous restera plus qu analyser:
# 2010-02-19 10:33:31 [11] user: root, db: livremyisam
Query: "select * from clients where adresse1 like '%A%'"
Norm_Query: "SELECT * FROM `clients` WHERE `adresse1` LIKE ? "
query_time: 1004.00 us
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 4 Mthodes et outils de diagnostic 75
global(avg_query_time): 1091.57 us
global(stddev_query_time): 2087.51 us
global(count): 7
query(avg_query_time): 1004.00 us
query(stddev_query_time): -1.#J us
query(count): 1
Le rpertoire share\doc\mysql-proxy contient aussi le fchier histogram.lua qui vous
permettra dobtenir un histogramme des requtes.
Dautres outils sont disponibles sur les sites suivants:
http://www.mysqlperformanceblog.com/tools/
http://hackmysql.com/
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
5
Techniques doptimisation
standard au niveau
base de donnes
5.1 Statistiques sur les donnes
Les statistiques sont fondamentales pour le fonctionnement du CBO (Cost Based
Optimizer). Des statistiques errones ou non reprsentatives peuvent le conduire
utiliser un plan dexcution inadapt qui pourrait donc entraner des performances
moins bonnes que ce quelles pourraient tre.
Sous Oracle 10g, le job GATHER_STATS_JOB est prconfgur pour collecter les sta-
tistiques. Sous Oracle11g, cest le package DBMS_AUTO_TASK_ADMIN qui gre cette
activit. Cette tche est paramtre pour seffectuer durant la plage de maintenance
qui est, par dfaut, confgure de 22heures 2heures en semaine et de 6heures
2heures le week-end. La base ne sera pas forcment entirement analyse chaque
fois. La collecte commencera par les objets qui nont pas de statistiques ou qui ont
t le plus modifs.
En cas de cration dune table ou si la nature des donnes change de faon signifca-
tive, il faut forcer la collecte au lieu de simplement attendre la collecte automatique
suivante. Cest particulirement vrai en phase de dveloppement alors que le dve-
loppeur dtruit et recre des tables et charge des jeux de tests diffrents.
Ce chapitre prsente la collecte des statistiques. Vous trouverez lAnnexe B des
informations plus dtailles sur leur nature.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
78 tude et optimisation desrequtes Axe 2
5.1.1 Ancienne mthode de collecte
Historiquement, il fallait utiliser les commandes suivantes pour collecter les
statistiques:
ANALYZE TABLE <NomTable> COMPUTE STATISTICS;
ANALYZE INDEX <NomIndex> COMPUTE STATISTICS;
Oracle recommande de ne plus les utiliser pour la partie collecte des statistiques de
loptimiseur.
5.1.2 Nouvelle mthode de collecte
prsent, il est conseill dutiliser le package DBMS_STATS, qui a un niveau dana-
lyse plus pouss et fournit donc loptimiseur des informations plus dtailles que
lancienne mthode.
Ce package permet de grer les statistiques avec les oprations suivantes:
collecte des statistiques (Gathering Optimizer Statistics):
dune table (procdure GATHER_TABLE_STATS),
dun index (procdure GATHER_INDEX_STATS),
dun schma (procdure GATHER_SCHEMA_STATS),
de toute la base (procdure GATHER_DATABASE_STATS);
effacement de statistiques;
transfert de statistiques (export/import);
restauration danciennes statistiques;
gestion des statistiques des types utilisateurs (user-defned);
gestion des statistiques tendues (Oracle11g).
Parmi toutes ces oprations, la collecte des statistiques est lopration la plus utili-
se. Par dfaut, elle parcourt toutes les donnes des tables analyser. Cette opration
peut donc prendre un temps signifcatif sur de grosses bases de donnes. Dans ce
cas, il peut tre intressant de collecter les statistiques par chantillonnage laide
du paramtre ESTIMATE_PERCENT, prsent dans toutes les procdures GATHER_*.
La collecte des statistiques dune table implique la collecte pour la table, les colonnes
et les index associs cette table.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 79
Exemple de collecte des statistiques du schma scott:
execute dbms_stats.GATHER_SCHEMA_STATS('SCOTT');
Les oprations de transfert des statistiques peuvent servir mettre au point des
requtes sur une base de test moins remplie, partir des statistiques de la base de
production. Loptimiseur utilisant les statistiques pour faire ses choix, il se compor-
tera comme si la base de test contenait les donnes de production.
Concernant les statistiques des types utilisateurs (user-defned), elles sont utiles uni-
quement si vous utilisez des types utilisateurs dans vos tables et les index de domaine.
Vous naurez donc normalement jamais besoin des oprations qui y sont associes.
Les statistiques sont stockes dans la mtabase et accessibles via des requtes SQL
(voir AnnexeB). On peut constater quelles contiennent de nombreuses infor mations
sur les tables, les index et chaque colonne.
Les principales informations collectes sur les tables sont:
le nombre denregistrements;
lespace occup en bloc;
la taille moyenne dun enregistrement.
Les principales informations collectes sur les index sont:
le nombre denregistrements;
le nombre de blocs feuilles;
des informations relatives au foisonnement (voir AnnexeB, section B.4).
Les principales informations collectes sur les colonnes sont:
le nombre de valeurs distinctes et nulles;
les valeurs hautes et basses;
la taille moyenne des donnes de la colonne;
la densit de la colonne (voir ci-aprs).
Au-del de leur utilisation par loptimiseur, certaines de ces statistiques peuvent
tre utiles pour avoir des informations sur la base de donnes. En effet, laide de
ces statistiques, le dveloppeur ou le DBA peut reprer facilement les plus grosses
tables, les colonnes qui ne sont jamais remplies,etc.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
80 tude et optimisation desrequtes Axe 2
5.1.3 Slectivit, cardinalit, densit
La slectivit est lestimation de la fraction de lignes slectionnes lors dune opra-
tion de fltrage. Elle permet de calculer la cardinalit dune opration qui est gale :
(Nombre de lignes Nombre de Valeurs NULL) Slectivit.
On dira, par exemple, que la condition NoCmd=123456 sur la table des commandes
contenant un million denregistrements a une forte slectivit puisquelle rduit
la slection une ligne sur un million et que la condition DateCommande>To_
Date(1/1/2009,dd/mm/yyyy) a une faible slectivit car elle fltre seulement
37% des valeurs (374311lignes sur un million de lignes).
On voit que la slectivit dpend de la nature des donnes et de la nature des condi-
tions. Ainsi, lorsquune condition est une galit, la slectivit est gale la densit
de la colonne (colonne Density des statistiques).
La densit est dfnie par
1
NombreValeurDistincte
. On voit que, plus il y a un nombre
de valeurs distinctes important, meilleure est la slectivit.
Lorsquune condition est un intervalle (oprateurs BETWEEN, <, >), la slectivit vaut:
taille de ltendue de lintervalle
taille de ltendue de la colonne
, la taille de ltendue de la colonne tant dtermine

par les colonnes Low_Value et High_Value (les chanes de caractres et les dates sont
converties en une valeur numrique).
Si lintervalle est ouvert (par exemple, NoCmd > 1000), on considre quil sarrte
la borne du ct ouvert.
Notez que, par dfaut, le SGBDR considre que les donnes sont linairement rpar-
ties. Nous verrons plus tard comment les histogrammes permettent dintgrer le fait
que ce nest pas toujours le cas.
Dans certains cas, le SGBDR utilise des valeurs fxes pour la slectivit car il na pas
dlments permettant de calculer la slectivit.
Lutilisation dune fonction implique potentiellement une densit du rsultat de la
fonction diffrente de celle de la colonne passe en paramtre. Concernant lutilisa-
tion dun LIKE commenant par un caractre % ou _, le SGBDR ne possde aucune
statistique sur le fait quune chane contienne telle ou telle sous-chane, il ne peut
donc estimer aucune slectivit fonde sur les statistiques. Un LIKE ne commenant
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 81
pas par un % est considr comme un intervalle, ainsi Nom like I% sera converti
en Nom >=I and Nom<J par loptimiseur.
Condition Slectivit
Fonction(Nom)='XX' 1%
Fonction(Nom)<>'XX' 5%
Fonction(Nom)>'XX' 5%
Utilisation du binding: Nom>: B (voir Chapitre8, section8.3, "Utilisation du
binding")
5%
Utilisation de like : Nom like '%I%'
5%
Combinaison des conditions
Lorsquil y a plusieurs conditions, le SGBDR considre quelles sont indpendantes
et multiplie donc les slectivits entre elles. Cette logique marche globalement tant
que les colonnes sont indpendantes, mais lorsquelles sont corrles, les rsultats
sont errons.
Prenons un exemple avec la requte suivante, sachant que la ville Berlin est situe
dans le pays Germany:
select * from clients where ville='Berlin' and pays='Germany'
Analysons le comportement du SGBDR:
Nombre d'enregistrements dans la table clients 45000
Slectivit de pays='Germany' 10,1%
Estimation de pays='Germany' 4546enregistrements
Slectivit de ville='Berlin' 0,1%
Estimation de ville='Berlin' 34enregistrements
Slectivit combine 0,01% (10,1 % 0,1 %)
Estimation de pays='Germany' And ville='Berlin' 4enregistrements
Nombre rel d'enregistrements vrifant pays='Germany' And
ville='Berlin'
34enregistrements
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
82 tude et optimisation desrequtes Axe 2
Nous constatons qu'il y a une erreur de facteur8 (4enregistrements au lieu de34),
ce qui risque de conduire l'optimiseur choisir un chemin d'excution inadapt
dans certaines requtes.
Ce problme peut tre contourn avec lutilisation de lchantillonnage dynamique
(Dynamic Sampling), activable laide du hint DYNAMIC_SAMPLING (voir Chapitre7,
section7.1, "Utilisation des hints sous Oracle").
/*+ dynamic_sampling(AliasDeTable Niveau) */
Le premier paramtre du hint est lalias de la table sur laquelle il faut faire lchan-
tillonnage dynamique. Le second paramtre est le niveau dchantillonnage. Celui-
ci peut prendre les valeurs110: la valeur1 chantillonne sur 32blocs de donnes,
les valeurs2 9 chantillonnent de 2 256blocs, la valeur10 analyse toute la table.
select /*+ dynamic_sampling(c 1) */ * from clients c
where ville='Berlin' and pays='Germany'
Cette nouvelle version de la requte utilisant le hint DYNAMIC_SAMPLING donne
une cardinalit de lopration de32, ce qui est trs proche de la ralit qui est de
34enregistrements.
Donnes non rparties linairement
Nous avons vu prcdemment que, lors de la slection dintervalles, le SGBDR
considre par dfaut que les donnes sont rparties linairement entre la borne basse
et la borne haute. Cependant, ce nest pas toujours le cas.
Cela arrive lorsque les donnes ne sont naturellement pas rparties linairement.
Par exemple, dans un annuaire national, il y aura plus de personnes Paris quen
Ardche.
Cela arrive aussi lors de lutilisation de valeurs spciales comme on peut en retrou-
ver dans certains modles de donnes. Imaginez que vous ayez besoin de pouvoir
affecter des employs un dpartement Non affect. Vous donnez ce dpartement
un numro spcial, par exemple 9999999, bien en dehors de la plage des numros
classiques, compris par exemple entre 0 et 10000, afn de ne pas le confondre avec
les autres numros de dpartements (cela aurait aussi pu tre0 ou 999999).
Vous vous retrouvez ainsi avec 99,99% des valeurs entre 0 et 10000 et quelques
valeurs 9999999.
Cependant, loptimiseur, considrant que les donnes sont rparties linairement,
estime quentre 0 et 1000 il y a 0,01% des valeurs alors quil y en a plutt 10%.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 83
Rpartition relle
NbVal
Valeurs
0
100
10 000 9 999 999
Hypothse optimiseur
sans histogramme
Figure5.1
Comparaison de rpartitions relle et linaire.
Afn damliorer les performances de loptimiseur sur des donnes non rparties
linairement, le SGBDR met les histogrammes notre disposition. Ils seront un
moyen de synthtiser la rpartition des donnes et de rsoudre le problme des
valeurs extrmes particulires et, dans certaines limites, celui des rpartitions non
linaires des donnes.
Il existe deux types dhistogrammes:
de frquence;
de distribution.
Lhistogramme de frquence calcule pour chaque valeur distincte le nombre doc-
currences. Il est utilis pour les distributions ayant peu de valeurs distinctes (moins
de100valeurs). Il est directement utilis pour calculer la slectivit lors des tests
dgalit.
Lhistogramme de distribution coupe les donnes en ntranches gales et dtermine
les bornes de chaque tranche.
Normalement, le SGBDR dtectera les colonnes sur lesquelles le calcul dun histo-
gramme est pertinent et dterminera le type dhistogramme en fonction du nombre
de valeurs distinctes.
Vous trouverez des informations plus dtailles sur les histogrammes lAnnexeB,
sectionB.3.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
84 tude et optimisation desrequtes Axe 2
Statistiques tendues (11g)
Oracle 11g introduit la notion de statistiques tendues qui permet de crer des
statistiques (y compris des histogrammes) sur des ensembles de colonnes ou des
expressions en utilisant la fonction DBMS_STATS.CREATE_EXTENDED_STATS (own-
name, tabname, extension). ownname et tabname permettent de dsigner la table
et extension contient soit une liste de colonnes entre parenthses spares par des
virgules, soit une expression entre parenthses. Cette fonction retourne le nom de la
statistique et nest donc pas utilisable directement avec linstruction EXEC mais peut
tre appele depuis une instruction SELECT:
Select dbms_stats.create_extended_stats(null,'CLIENTS','(PAYS,VILLE)')
AS NomStat from dual;
Cette instruction a pour effet de crer une statistique sur la combinaison de colonnes
Pays,Ville de la table clients du schma courant.
Nous forons le calcul dun histogramme sur cette colonne (opration qui ne sera
gnralement pas ncessaire):
exec dbms_stats.gather_table_stats(null,'clients',method_opt => 'for columns
SYS_STUNUIEHWAFAS55IIEQVJJF#W$ size 254');
SYS_STUNUIEHWAFAS55IIEQVJJF#W$ est la valeur retourne par linstruction
SELECT de cration de la statistique tendue ou par la requte suivante qui permet de
rcuprer le nom dune statistique tendue.
Select dbms_stats.show_extended_stats_name(null,'clients','(PAYS,VILLE)')
AS NomStat FROM dual;
Une fois lhistogramme cr et les statistiques actualises, si on excute nouveau
la requte suivante:
select * from clients where ville='Berlin' and pays='Germany'
nous pouvons constater que lestimation par loptimiseur de la requte est prsent
de 41enregistrements au lieu de 4enregistrements initialement estims ce qui est
plus proche de la ralit qui est de 34lignes. Cependant, cette estimation est moins
bonne que celle faite par lchantillonnage dynamique mais elle est moins coteuse.
Nous avons vu prcdemment que lutilisation de fonctions dans des prdicats
conduisait loptimiseur utiliser des valeurs prdfnies. Il estime ainsi que la
requte ci-aprs retourne 1% des enregistrements de la table:
select * from clients where upper(adresse1)='887 PONCE STREET'
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 85
Si nous crons une statistique sur lexpression et si nous collectons les statistiques
de la table clients, nous constatons que loptimiseur estime prsent correctement
quil ny a quune seule ligne slectionne, ce qui est bien le cas:
select dbms_stats.create_extended_stats(null,'clients','(upper(adresse1))')
from dual;
exec dbms_stats.gather_table_stats(null,'clients');
MS SQL Server
Sous SQL Server, les statistiques ne sont pas systmatiquement calcules pour chaque co-
lonne, par contre, elles intgrent systmatiquement un histogramme sur les cls d'index
primaires et secondaires.
Les instructions CREATE STATISTICS et UPDATE STATISTICS permettent de crer et de
mettre jour des statistiques manuellement.
SQL Server donne, comme les statistiques tendues d'Oracle11g, la possibilit de calculer
des statistiques sur des combinaisons de colonnes afn de rsoudre le problme de la
mauvaise estimation des combinaisons de conditions.
MySQL
MySQL intgre aussi des statistiques et des histogrammes.
L'instruction ANALYZE TABLE permet de forcer la collecte des statistiques.
Certaines donnes des statistiques sont consultables en interrogeant la table
INFORMATION_SCHEMA.STATISTICS mais il y a bien plus d'informations que celles prsen-
tes dans cette table indpendante des moteurs, car la gestion des statistiques est propre
chaque moteur.
5.2 Utilisation des index
Un premier type doptimisation consiste mettre en place des objets ddis lopti-
misation des tables: les index. Sous Oracle, ils peuvent tre soit de type B*Tree soit
de type bitmap. Leur action est gnralement assez effcace, sans pour autant que
leur mise en place ncessite beaucoup de changements au niveau de lapplication.
Le tout sera de choisir le type dindex le plus adapt la situation. Les index prsen-
tent lavantage de pouvoir tre galement mis en uvre au sein de logiciels raliss
par des tiers et pour lesquels vous navez pas accs au code source.
Les index, dune manire gnrale, permettent damliorer parfois considra-
blement les performances en lecture, mais ils peuvent lgrement dgrader les
performances en criture car le SGBDR doit les maintenir en plus des tables lors
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
86 tude et optimisation desrequtes Axe 2
des modifcations des donnes indexes (insertion, modifcation de la cl dindex,
suppression de lenregistrement). Sur des tables qui ont des accs en criture trs
concurrents, la mise jour des index peut provoquer des contentions daccs ceux-
ci et donc des latences dcriture.
5.2.1 Index B*Tree
Utiliss historiquement par les bases de donnes relationnelles, les index B*Tree
sont prsents dans de nombreux SGBDR.
Leur principe est de contenir les valeurs des cls de lindex de faon ordonne
dans une structure arborescente. Ainsi, ils permettent de trouver trs rapidement
une valeur prcise en parcourant larbre de la racine vers les feuilles et non pas en
recherchant la valeur dans lensemble des enregistrements de la table. De plus, les
feuilles sont chanes entre elles (voir Figure5.2). Aussi, lorsquil est ncessaire de
parcourir lindex squentiellement, on passe de feuille en feuille sans devoir remonter
au niveau des branches.
Un index B*Tree porte sur une ou plusieurs colonnes quon appelle "cls de lin-
dex". Suivant le type de lindex, les cls doivent tre uniques (dans le cas dindex
uniques) ou peuvent contenir des doublons. Elles peuvent tre des champs de type
numrique, date ou chane de caractres mais pas de type BLOB ou CLOB. Lors de
la cration de lindex, on spcife pour chaque champ de la cl son ordre de tri qui,
par dfaut, sera ascendant (ASC) mais peut tre dcroissant (DESC) comme dans la
clause ORDER BY de linstruction SELECT.
Pour comprendre le fonctionnement, prenons un exemple. Pour obtenir lenregistre-
ment ayant pour cl la valeur 1015 dans lindex B*Tree reprsent la Figure5.2,
le SGBDR va procder de la manire suivante:
1. Il parcourt le bloc racine jusqu ce quil rencontre une valeur suprieure.
2. Il va sur le bloc point par la valeur qui prcde, ce qui le conduit au premier
bloc branche.
3. Dans le bloc branche, il rpte la mme opration, ce qui le conduit un bloc
feuille.
4. Dans le bloc feuille, il recherche la valeur. Sil ne la trouve pas, il sarrte la
premire valeur suprieure rencontre et renvoie linformation signalant que
la valeur recherche nexiste pas dans la table. Sil la trouve, lentre dindex
point permet dobtenir le RowID de lenregistrement correspondant.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 87
5. Le RowID permet de rcuprer lenregistrement dans le tas (heap).
Bloc Racine
Root Blocks
Blocs Branche
Branch Blocks
Blocs Feuille
Leaf Blocks
Le RowID permet de pointer sur les lignes stockes dans le Tas
Table Heap :
Donnes non ordonnes
20 000
50 000

150 000
240 000
1 000
2 000

15 000
16 000
0
1

998
999
ROWID
ROWID
ROWID
ROWID
1 000
1 015

1 700
1 900
ROWID
ROWID
ROWID
ROWID
20 000
21 000

35 000
47 000

4 521
582

874
1 015
LECLERC
DUPOND

ROCHE
BERTHIER
OPRATEUR
COMMERCIAL

COMMERCIAL
MANAGER

2 586
325

1
999
MARTIN
GUY

BERGER
LEGRAND
COMMERCIAL
MANAGER

COMMERCIAL
MANAGER

Figure5.2
Exemple de parcours d'un index B*Tree.
On constate que nous avons besoin de lire seulement trois blocs de donnes dindex
plus un bloc de donnes dans la partie tas de la table pour obtenir lenregistrement,
alors quun parcours complet de la table aurait ncessit daccder tous ses blocs.
La hauteur de larbre est variable mais excde rarement trois ou quatre niveaux. Si
on considre quun bloc non feuille peut pointer sur 100 500blocs (cela dpend
de la taille de la cl), lexemple prcdent (dune hauteur de trois) pourrait avoir
10 000 250 000 feuilles. La hauteur de larbre a une progression logarithmique
par rapport au nombre denregistrements dans la table. Puisque le nombre daccs
ncessaires pour accder un lment dpend de la hauteur de larbre, il est donc
lui aussi logarithmique.
Sans index, sur une table de nlignes, il faut en moyenne parcourir n/2lignes pour
trouver une ligne unique et nlignes pour trouver toutes les occurrences dune valeur
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
88 tude et optimisation desrequtes Axe 2
dans une colonne non unique alors que, dans un index, il faut en moyenne parcourir
une proportion de log(n) lignes pour trouver une ligne. Par exemple, pour une table
dun million denregistrements, sans index il faudra parcourir 1000000 denregis-
trements alors quavec un index il suffra de parcourir environ 30enregistrements.
tant donn la progression logarithmique, accder un enregistrement en passant
par une cl indexe sur une table de 10millions denregistrements ne ncessitera pas
beaucoup plus daccs que sur une table de 10000enregistrements.
Par dfaut, toutes les cls primaires ont un index B*Tree unique qui est cr auto-
matiquement lors de la dclaration de la cl primaire.
Nous venons de voir que, plus il y a denregistrements dans une table, plus le gain
est grand. Le corollaire est vrai aussi: moins il y a denregistrements dans une table,
moins lintrt dun index est grand. En effet, sur des petites tables moins de
1000lignes et ayant des lignes de petite taille, il nest pas pertinent dajouter des
index. Lorsque des index sont prsents mais inutiles, ils ne servent pas car lopti-
miseur ny voit aucun intrt. Ils sont par contre maintenus et occupent de lespace.
Nous avons vu que la dernire tape consiste rcuprer lenregistrement partir
du RowID obtenu dans le B*Tree. Cette opration est plutt performante puisque
le RowID contient ladresse du bloc contenant lenregistrement. Cependant, lorsque
plusieurs valeurs sont recherches par le biais de lindex, le SGBDR fait des va-et-
vient entre lindex et le tas qui peuvent, fnalement, tre assez coteux. Donc, si
loptimiseur estime quil va rcuprer travers lindex plus de 5% des donnes de la
table, il choisira de ne pas lutiliser. En effet, au-del de ce seuil (approximatif), les
performances risquent de se dgrader et il sera moins performant dutiliser lindex
que de ne pas lutiliser.
Le nombre de lignes rcupres dans lindex dpend soit de la nature des donnes,
soit de la nature des conditions. Ainsi, il ne sera pas pertinent de placer des index
sur des colonnes qui ont beaucoup de valeurs dupliques (cest--dire peu de valeurs
distinctes) puisque, quelle que soit la condition sur ce genre de colonne, loptimiseur
estimera que trop de lignes seront rcupres pour que cela soit intressant. De la
mme faon, il nest pas surprenant quun index ne soit pas utilis sur des conditions
peu slectives qui auraient pour effet la rcupration dun grand nombre de lignes.
Loptimiseur dcidera de lusage dun index en fonction de lestimation quil aura
faite du nombre de lignes quil va rcuprer. Cette information dpend de limage
que loptimiseur a des donnes et de sa capacit estimer la slectivit des conditions.
On voit ici tout lintrt davoir des statistiques fdles aux donnes.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 89
Il existe cependant un cas o, mme sil y a un grand nombre denregistrements
concerns, loptimiseur choisira dutiliser lindex coup sr : les requtes o le
parcours seul de lindex sufft obtenir la rponse.
select count(*) from clients
where noclient between 10000 and 100000
Dans lexemple prcdent, le parcours de lindex de la cl primaire (Noclient) sufft
pour rpondre la requte. Il est donc utilis malgr le fait quil rcupre 60% des
enregistrements. La requte suivante, elle, qui ncessite davoir accs au tas de la
table pour tester le champ Nom, nutilise pas lindex, car les va-et-vient entre lindex
et le tas sont trop pnalisants sur un tel volume.
select count(*) from clients
where noclient between 10000 and 100000 and Nom is not null
Les index contenant les valeurs des cls de faon ordonne, ils pourront aussi tre
utiliss pour les tris. Des tris peuvent tre ncessaires dans diffrentes situations,
telles que lutilisation dune clause ORDER BY, DISTINCT ou GROUP BY dans une
requte ou le recours par loptimiseur des jointures de type Sort-Merge. Notez
quun index class de faon ascendante pourra tre utilis aussi bien pour des tris
ascendants que descendants, la diffrence entre le sens du tri de lindex et celui du
tri demand nest gnralement pas signifcative.
ATTENTION
L'utilisation d'index a un impact lors des accs en criture. Le cot de maintien des index est
relativement faible mais, s'il y en a beaucoup et que la table subisse de nombreuses modif-
cations, cela peut fnalement devenir signifcatif.
Sur un autre plan, les index occupent de l'espace de stockage. Cet espace est, pour simplifer,
celui qui est requis pour les feuilles et qui correspond l'espace ncessaire pour les valeurs
des cls plus 1RowID par enregistrement. Il peut tre signifcatif, voire dpasser l'espace de
la table si toutes les colonnes sont indexes ou s'il y a de nombreux index.
Si vous avez un doute sur le fait qu'un index soit utilis, vous pouvez le mettre sous sur-
veillance l'aide de l'instruction suivante:
alter index Nom_Index monitoring usage;
puis vrifer, quelques jours ou semaines plus tard, s'il a t utilis depuis l'activation de la
surveillance en consultant la colonne Used de la requte suivante:
SQL> select * from v$object_usage;
INDEX_NAME TABLE_NAME MONITORING USED START_MONITORING END_MONITORING
--------------- -------------------- ---------- ---- ------------------- -------------------
IS_CLIENTS_NOM CLIENTS YES NO 01/22/2010 10:48:32
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
90 tude et optimisation desrequtes Axe 2
Combinaison des index B*Tree et index composites
De faon gnrale, un seul index B*Tree peut tre utilis par accs une table. Si
le plan dexcution ncessite plusieurs accs la mme table (autojointure, par
exemple), des index diffrents pourront tre utiliss pour chaque accs. Cela signi-
fe que si une requte contient deux conditions sur deux colonnes indexes spar-
ment, alors seulement lindex le plus pertinent sera utilis et le second ne servira
rien. Dans des cas comme celui-l, il peut tre intressant dutiliser des index
composites (aussi appels index "multicolonnes") qui permettront dindexer plu-
sieurs colonnes.
Lordre des colonnes a son importance, nous allons lillustrer par quelques exemples:
Un index composite Pays,Ville sera trs effcace dans les cas suivants:
where Pays='France' and ville='Toulouse'
where Pays='France' order by ville
where Pays='France' group by ville
order by pays,ville
Moyennement effcace dans les cas suivants:
Where ville='Toulouse'
Un index composite Ville, Pays sera trs effcace dans les cas suivants:
where Pays='France' and ville='Toulouse'
Where ville='Toulouse'
Moyennement effcace dans les cas suivants:
where Pays='France' order by ville
Ineffcace dans les cas suivants:
order by pays,ville
Un index composite sera le plus effcace dans les cas suivants:
prsence de conditions sur toutes les colonnes de lindex;
prsence de conditions sur toutes les premires colonnes de lindex;
ncessit dun tri suivant lordre de lindex;
prsence dune combinaison entre une condition sur les premires colonnes de
lindex et un tri suivant lordre de colonnes restantes de lindex.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 91
Un index composite sera peu effcace mais potentiellement intressant malgr tout
dans les cas suivants:
Sil y a des conditions sur des colonnes dun index qui ne soient pas conscutive-
ment les premires de lindex. Dans ce cas, loptimiseur pourra dcider de faire
un Skip Scan de lindex.
Un tri sur les premires colonnes et des conditions sur les colonnes restantes
de lindex car dans ce cas lindex devra tre parcouru entirement de faon
squentielle.
Un index composite sera ineffcace dans de nombreux cas, mais plus particulire-
ment si la requte ncessite un tri sur les colonnes de lindex mais dans un ordre
diffrent de celui de lindex.
Cas disqualifant les index
Nous avons vu que loptimiseur dcidait dutiliser les index quand il pensait que leur
usage allait amliorer les performances. Il faut cependant avoir en tte quil existe
des cas pour lesquels les index ne seront pas utiliss, car ils sont inutilisables.
Lutilisation de like %..., cest--dire un LIKE dont le masque commence par
une chane libre, ne permet pas dutiliser un index en mode Unique Scan ou Range
Scan.
Lutilisation de fonctions ou plus gnralement dexpressions sur les colonnes
empche celle des index. Nanmoins, lutilisation dindex sur fonction que nous
tudierons plus tard permet dapporter une solution cette limitation si ncessaire.
Par exemple, les instructions suivantes empchent lutilisation des index sur les
colonnes Noclient et Ville.
select * from clients where noclient*10=40000 ;
select * from clients where upper(Ville)='PARIS' ;
INFO
Une condition entrant dans un des cas disqualifants pourra tre applique malgr tout
surl'index si l'optimiseur a dtermin pour d'autres raisons que l'index pouvait tre int-
ressant.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
92 tude et optimisation desrequtes Axe 2
Quelles colonnes indexer?
Souvenez-vous, les cls primaires sont, par dfaut, indexes, mais quelles autres
colonnes est-il pertinent dindexer? On la vu, les index ont un cot, aussi bien en
termes de ressources pour les maintenir jour quen espace occup. Il nest donc
pas intressant de les maintenir sils ne servent quasiment jamais. Je vous conseille
donc dindexer:
Les colonnes les plus utilises dans les clauses WHERE sans quelles entrent dans
les cas disqualifants.
Les colonnes les plus utilises dans les jointures. Cela pourra favoriser lusage
de Sort Merge Join et rendra les Nested Loop plus performantes. Pour les Hash
Join, lintrt sera de constituer la table de hachage (hash table) partir de lin-
dex plutt que la table.
Les colonnes qui ont une densit (nombre valeurs distinctes/nombre lignes)
faible (infrieure 5 %) en relation bien sr avec le premier point. Inutile de
crer des index qui ne servent rien.
Les colonnes flles de cl trangre (Foreign Key) si la table mre subit des
DELETE. En effet, chacun deux provoquera une requte sur ses tables flles pour
contrler le respect des contraintes dintgrit rfrentielle (CIR).
Mise en uvre
La syntaxe de base permettant de crer un index et un index unique est la suivante:
create index <Nom_Index> on <NomTable>(<col1>[,<col2>,])
create unique index <Nom_Index> on <NomTable>(<col1>[,<col2>,])
Nous avons dj tudi limpact des histogrammes sur les statistiques. Nous allons
tester ici comment cela va se traduire par lutilisation ou non dun index.
Par exemple, si nous crons un index is_clients_pays sur la colonne Pays de la
table clients laide de linstruction suivante:
create index is_clients_pays on clients(pays);
et que nous testions la requte suivante avec et sans histogramme:
select * from clients where pays='Cameroun'
la Figure5.3a, la slectivit du prdicat est estime par la densit de la colonne
2% avec un fort foisonnement, et lindex ne sufft pas rpondre. Loptimiseur
dtermine donc quil sera moins coteux de faire un Full Table Scan.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 93
la Figure5.3b, lhistogramme de frquence permet de dterminer une slectivit
plus forte du prdicat sur la colonne Pays 0.07%. Loptimiseur dtermine donc
quil est plus intressant dutiliser lindex is_clients_pays. Nous remarquons que
cela rduit considrablement les Consistent Gets en les divisant par20.
Figure5.3a
Sans histogramme.
Figure5.3b
Avec histogramme.
Si nous excutons la mme requte avec pays=USA, alors lhistogramme retourne
une estimation de 40% des enregistrements. En toute logique, loptimiseur dcide
deffectuer un Full Table Scan puisque lutilisation de lindex sur un tel pourcentage
de la table serait pnalisante. On constate bien que le plan dexcution dpend de la
nature des conditions mais aussi des donnes des conditions et de la table.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
94 tude et optimisation desrequtes Axe 2
ASTUCE
Le SGBDR fabrique automatiquement l'histogramme sur la colonne Pays. Afn d'empcher
sa cration pour les besoins de notre dmonstration, nous excutons:
execute dbms_stats.gather_table_stats (user,'clients',cascade
=> true, method_opt => 'for columns pays size 1');
La cration d'un histogramme sur un seul intervalle a pour effet d'empcher la cration de
ce dernier.
Cependant, c'est parfois le cas inverse qui se produit. Ainsi, si Oracle ne cre pas d'histo-
gramme sur une colonne alors que vous pensez que cela serait pertinent, vous pouvez forcer
l'opration l'aide de l'instruction suivante. Il est cependant probable que l'histogramme
ne sera pas conserv; lors du prochain calcul des statistiques, il faudra donc intgrer cette
instruction un job priodique:
execute dbms_stats.gather_table_stats (user,'clients',cascade
=> true, method_opt => 'for columns pays size 254');
Compression d'index
La compression permet dviter la rptition des valeurs des premires colonnes de
la cl dans un index composite et, ainsi, de rduire le nombre de blocs manipuler.
Cela amliore leffcacit de lindex. La compression ntant possible que sur les
n-1 premires colonnes dun index, cette fonction est rserve aux index compo-
sites. Son objectif est de faire gagner de lespace dans les feuilles afn den rduire le
nombre. Compresser des colonnes avec peu de doublons pourra entraner une perte
deffcacit.
Exemple dun index compress:
Create index IS_CLIENTS_PAYS_VILLE on Clients(Pays,ville) compress 1;
Cet index compressera les pays qui ne seront rpts quune seule fois par feuille.
MS SQL Server
SQL Server 2005 ne propose pas de mcanisme de ce genre. SQL Server 2008 introduit
une compression analogue celle des tables que nous tudierons la section5.3.1 de ce
chapitre.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 95
MySQL
Le moteur MyISAM offre la possibilit de compresser les index l'aide de l'option PACK_
KEYS confgure au niveau de la table.
Par dfaut, si PACK_KEYS n'est pas mentionne, les npremiers caractres communs des
chanes de caractres sont compresss. PACK_KEYS=1 force en plus la compression des
valeurs numriques. PACK_KEYS=0 dsactive cette fonction.
Le moteur InnoDB ne propose pas de compression d'index suivant le mme principe,
mais plutt une compression des pages d'index et de table que nous tudierons la
- section5.3.1 de ce chapitre.
Comportement des index avec les valeurs nulles
Les SGBDR ont rgulirement des comportements droutants ds quil sagit de
manipuler les valeurs nulles, et lutilisation des index nchappe pas la rgle.
Le SGBDR Oracle nindexe pas les lignes contenant des NULL sur les premires
colonnes pour lesquelles toutes les colonnes prsentes dans lindex sont nullables
(cest--dire qui ne sont pas dclares comme NOT NULL). Cela signife quun index
monocolonne ne grera jamais les valeurs nulles, il ne sera donc jamais utilis sur
un prdicat IS NULL.
Si un index est compos de plusieurs colonnes et quau moins une de ces colonnes
soit dsigne NOT NULL, le prdicat IS NULL pourra lutiliser. Cest un cas assez
restrictif, donc retenez plutt que, en gnral, les valeurs nulles ne fonctionnent pas
avec les index.
La valeur nulle est souvent utilise comme valeur spciale. Par exemple, dans notre
table des commandes, nous aurions pu avoir une colonne DateLivraison et recher-
cher les commandes non livres avec le prdicat DateLivraison IS NULL. Nous
aurions pu penser quen mettant un index sur cette colonne, la recherche aurait t
performante, mais nous nous serions tromps. Dans un cas comme celui-ci, deux
solutions soffrent nous: la premire est dutiliser un champ EtatCommande, la
seconde consiste ajouter un champ NOT NULL dans lindex B*Tree.
Il faudra donc, si cest possible, viter dutiliser la valeur nulle comme valeur sp-
ciale ou alors crer un index composite qui englobe en plus de cette colonne une
colonne qui nest pas nullable.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
96 tude et optimisation desrequtes Axe 2
Afn de vrifer ce que nous venons dexpliquer, regardons ce quil se passe si nous
crons un index sur la colonne Email et que nous recherchions les clients nayant
pas dadresse e-mail:
Create index IS_CLIENTS_EMAIL on Clients(email);
select * from clients where email is null;
Figure5.4a
Plan d'excution
d'une requte IS NULL
n'utilisant pas l'index.
Nous constatons que lindex is_clients_email nest pas utilis. Par contre, si nous
crons un index composite sur le champ Email et sur le champ Noclient qui est la
cl primaire et qui nest donc pas nullable , lindex est bien utilis avec le prdicat
Email Is Null.
Create index IS_CLIENTS_EMAIL_NOCLIENT on Clients(email,NoClient);
select * from clients where email is null;
Figure5.4b
Plan d'excution
d'une requte IS NULL
utilisant un index.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 97
MS SQL Server et MySQL
Aussi bien sous SQL Server que sous MySQL, le comportement des valeurs nulles lors de
l'utilisation des index n'a rien de particulier. La valeur nulle est considre comme une
valeur comme une autre et les index sont bien utiliss sur les prdicats IS NULL.
Colonnes incluses
Nous avons vu que si loptimiseur trouve toutes les donnes dans lindex, il peut
dcider de ne pas accder la table. Ce comportement peut tre exploit pour am-
liorer les performances en incluant dans des index les donnes que vous souhaitez
rcuprer, on parle alors dindex "couvrant". Par exemple, si vous souhaitez souvent
rcuprer la liste des noms des clients dun pays, vous pouvez crer un index sur ces
colonnes, en mettant imprativement en premier celles qui servent de critre et en
second celles qui sont les colonnes incluses.
create index IS_CLIENTS_PAYSNOM on CLIENTS (PAYS, NOM);
select nom from clients t where pays='Cameroun';
On constate dans le plan dexcution de la Figure5.4c que seul lindex est utilis.
Cela conomise laccs la table quaurait ncessit un index sur la colonne Pays
seule.
Figure5.4c
Plan d'excution
d'une requte utilisant
un index incluant toutes
les colonnes.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
98 tude et optimisation desrequtes Axe 2
MS SQL Server
Sous SQL Server, cette approche est intgre dans la syntaxe l'aide du mot cl INCLUDE
qui permet d'ajouter des champs l'index sans qu'ils soient inclus dans l'arbre ni comme
cl de tri mais seulement dans les feuilles.
create index IS_CLIENTS_PAYSNOM on CLIENTS (PAYS) INCLUDE(nom);
On constate la nuance par le fait que, sous Oracle, le rsultat apparat tri par nom
puisqu'il s'agit d'un parcours de l'index qui est tri sur Pays et Nom alors qu'avec la syn-
taxe INCLUDE le rsultat n'est pas tri par Nom bien que, l aussi, seul l'index soit par-
couru. La diffrence est que la cl de tri de l'index sous SQL Server est seulement le champ
Pays, le champ Nom n'est pas stock dans un ordre particulier.
Le facteur de foisonnement
Le facteur de foisonnement (Clustering Factor) tablit le nombre de liens quil y a
entre lensemble des feuilles de lindex et les blocs dans le tas. Il permet destimer
si le fait que plusieurs valeurs se trouvent dans une mme feuille dindex ncessitera
plutt peu de lecture de blocs diffrents dans le tas ou plutt beaucoup.
Les donnes relatives au facteur de foisonnement sont disponibles dans la mtabase.
On y accde par la requte suivante.
select t.INDEX_NAME,t.LEAF_BLOCKS,t.DISTINCT_KEYS,t.CLUSTERING_FACTOR
from sys.user_ind_statistics t where index_name like '%CLIENT%';
INDEX_NAME LEAF_BLOCKS DISTINCT_KEYS CLUSTERING_FACTOR
------------------------------ ----------- --------------- ------------------
PK_CLIENTS 94 45000 759
IS_CLIENTS_VILLE 130 1096 43479
Clustering_Factor/Leaf_Blocks donne le nombre de liens quil y a en moyenne
entre une feuille et des blocs de donnes dans le tas: un ratio infrieur ou gal 3
est excellent.
Par contre, lorsque Clustering_Factor tend vers le nombre denregistrements, alors
le Clustering Factor est considr comme mauvais.
Prenons deux cas pour illustrer le facteur de foisonnement:
Premier cas. Lindex de cl primaire sur la colonne Nocmd de la table des com-
mandes cmd. Si on suppose que les numros de commandes sont crs squen-
tiellement, de faon ordonne et jamais effacs, le tas sera globalement dans le
mme ordre que lindex. Si lindex retourne plusieurs RowID depuis un mme
bloc (ce qui est caractristique dun prdicat sur une partie de cl ou sur un inter-
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 99
valle), alors il est probable que ces RowID dsignent le mme bloc ou peu de
blocs diffrents dans le tas (puisque, gnralement, il y aura plus de blocs dans
le tas que de blocs dindex). Dans ce cas, le facteur de foisonnement sera bon.
Second cas. Un index sur la colonne Ville dans la table des clients. Si on suppose
que les clients nagissent pas de faon concerte ou dirige, alors ils seront mis
dans le tas dans lordre suivant lequel ils ont pass leur premire commande mais
ils seront normalement dans des villes diffrentes. Donc, le fait de rechercher
tous les clients situs "Toulouse" retournera, depuis une ou plusieurs pages
conscutives de lindex, des RowID qui dsigneront des blocs qui seront proba-
blement sans aucun point commun. Dans ce cas, le facteur de foisonnement sera
mauvais.
Un bon facteur de foisonnement permettra davoir de meilleures performances lors
dune opration Index Range Scan puisque, pour chaque feuille dindex, il y aura peu
de blocs de donnes charger depuis le tas. Pour les autres types daccs, limpact sera
gnralement faible. Un mauvais facteur de foisonnement aura pour effet de consi-
drer un Index Range Scan moins intressant (voir lAnnexeB, sectionB.4, pour un
exemple dimpact). Il nest pas trop possible dinfuer sur le facteur de foisonnement.
5.2.2 Index sur fonction
Comme nous lavons vu prcdemment, lexcution de fonctions sur des colonnes
indexes a pour consquence que les index ne sont pas utiliss sur ces colonnes, ce
qui peut tre pnalisant.
Par exemple, la requte suivante ignore lindex qui est prsent sur la colonne Nom.
create index IS_CLIENTS_NOM on CLIENTS(NOM);
Select * from clients Where Upper(Nom)='NEVILLE';
Pour pallier ce problme, il est possible de crer des index sur fonction. Il sagit
dindex B*Tree classiques sauf que leur cl nest pas la valeur de la colonne indexe
mais le rsultat de la fonction sur la valeur de la cl. Dans notre exemple, lindex
contiendra donc Upper(Nom) et non pas Nom.
create index IS_CLIENTS_UPPER_NOM on CLIENTS(Upper(NOM));
Select * from clients Where Upper(Nom)='NEVILLE';
Malgr leur nom, les index sur fonction sappliquent aussi des expressions. Ainsi,
il est possible de dfnir un index sur une expression quelconque, condition quelle
soit dterministe et rptable (il est interdit dutiliser SYSDATE ou DBMS_RANDOM).
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
100 tude et optimisation desrequtes Axe 2
Lexemple ci-aprs cre un index sur une expression qui est utilise par la requte
suivante malgr le fait que les oprandes ont t permuts.
create index IS_CLIENTS_NOCLIENT10 on CLIENTS(NoClient+10);
Select * from clients Where 10+NoClient=14813
Oracle 11g introduit la notion de colonne virtuelle. Ce sont des colonnes calcules
dont le rsultat nest pas stock. Elles peuvent tre indexes et auront alors le mme
fonctionnement quun index sur fonction. Dans lexemple suivant, nous crons une
colonne virtuelle et nous lindexons: quon linterroge ou quon fasse une requte
sur sa dfnition, dans les deux cas lindex est utilis.
alter table clients add upper_nom varchar2(50) as (upper(nom));
create index is_clients_upper_nom on clients(upper_nom);
select * from clients t where upper(nom)='GORE';
select * from clients t where upper_nom ='GORE';
MySQL
MySQL ne propose ni la notion d'index sur fonction, ni la notion de colonne virtuelle.
MS SQL Server
SQL Server propose la fois la notion d'index sur fonction et la notion de colonne vir-
tuelle. Il est possible, pour cette dernire, de la dfnir "persistante", c'est--dire stocke
dans la table et non pas calcule la vole.
5.2.3 Reverse Index
Ce sont des index B*Tree qui indexent les valeurs miroirs (par exemple, le nom
"Jones" devient "senoJ"). La syntaxe est identique, il faut juste spcifer le mot cl
REVERSE la fn de linstruction:
Create index <Nom_Index> on <NomTable>(<col1>[,<col2>,]) REVERSE
Le but de ce type dindex est dviter que deux valeurs qui se suivent dans leur ordre
naturel se retrouvent dans la mme feuille. Lobjectif est ici de sorganiser pour
avoir un mauvais facteur de foisonnement. Dans quel intrt?
Imaginez une table dont la cl est un numro squentiel et quil y ait de nombreuses
insertions en parallle. On se retrouve alors avec plusieurs requtes qui vont vouloir
mettre jour la mme feuille dindex. Or, cette opration ne peut pas tre faite par
deux requtes simultanment: cela aurait pour effet de bloquer chacune delles le
temps que la prcdente ait termin la mise jour de la feuille dindex. Avec un
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 101
index reverse, elles vont mettre jour des feuilles dindex diffrentes et ainsi elles
ne se gneront pas. Cela permet donc de rduire la contention daccs en criture des
feuilles dindex, ce qui sera intressant sur des requtes parallles, particulirement
en environnement Oracle RAC. Cependant, ce type dindex montre des limites car
il nest utilisable que sur des conditions de type galit (=), ce qui signife quil ne
fonctionnera pas pour des oprations Index Range Scan.
De plus, contrairement une rumeur rpandue, ce type dindex ne fonctionne PAS
sur les requtes de type Nom like %nes, cest--dire avec un masque de LIKE
commenant par% et ayant une fn fxe.
5.2.4 Index bitmap
Les index bitmap sont adapts la manipulation de colonnes avec peu de valeurs
distinctes. Ils ne sont utilisables que pour des prdicats dgalit, mais Oracle arrive,
dans certains cas, convertir des intervalles par un ensemble dgalit, rendant ainsi
ces index oprants sur des intervalles et mme sur des jointures.
Les index bitmap sont des masques de bits pour les valeurs distinctes des colonnes
indexes : des ET et OU binaires permettent de faire des tests dgalit. Nous lil-
lustrons ci-aprs avec la table emp du schma scott des bases exemples dOracle.
On voit que la colonne Job peut prendre cinq valeurs possibles (voir Figure5.5a).
Lindex bitmap code ces valeurs par cinq masques de bits (voir Figure5.5b). Chaque
bit spcife par un1 que la ligne contient la valeur ou par un0 quelle ne la contient
pas. Si nous cherchons slectionner les personnes ayant un job de PRESIDENT
ou de COMPTABLE, il sufft de faire un OU binaire entre les deux masques pour
connatre les lignes qui ont une de ces valeurs (voir Figure5.5b). Lintrt le plus
signifcatif des index bitmap est quon peut en combiner plusieurs dans un mme
accs une table. Pour cela, il suffra dappliquer des oprations logiques sur les
diffrents masques de chaque index comme sil sagissait du mme index bitmap.
Les index B*Tree ne sont pas conus pour tre combins; ils ne peuvent donc pas
ltre effcacement. En revanche, sil y a plusieurs index bitmap couvrant les prdi-
cats dune requte, ils seront combins.
En fait, les index bitmap ne sont pas stocks comme cest prsent la Figure5.5b
car ils sont compresss. La technique de compression utilise est sensible au foison-
nement. Ainsi, si les lignes qui se suivent ont souvent la mme valeur, la compres-
sion sera bien meilleure que si chaque ligne a une valeur diffrente de la prcdente.
Le taux de compression aura un impact sur lespace requis pour stocker lindex
bitmap et donc sur le nombre de Consistent Gets. Il faut avoir en tte que, si les
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
102 tude et optimisation desrequtes Axe 2
valeurs distinctes sont distribues sur lensemble de la table plutt que regroupes
par paquets, lindex occupe plus despace.
Figure5.5a
Reprsentation logique
d'un index bitmap.
N


l
i
g
n
e
C
O
M
P
T
A
B
L
E
V
E
N
D
E
U
R
P
R
E
S
I
D
E
N
T
M
A
N
A
G
E
R
I
N
G
E
N
I
E
U
R
COMPTABLE
VENDEUR
VENDEUR
MANAGER
VENDEUR
MANAGER
MANAGER
INGENIEUR
PRESIDENT
VENDEUR
COMPTABLE
COMPTABLE
INGENIEUR
COMPTABLE
DUPOND
MICHEL
LEROY
DURAND
MEUNIER
MARTIN
DUPONT
LECLERC
NEUVILLE
DUJARDIN
BERTHIER
GUY
RENAUD
LAVAUR
14347
14484
14621
14758
14895
15032
15169
15306
15443
15580
15717
15854
15991
16128
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
0
0
0
0
0
0
0
0
0
1
1
0
1
0
1
1
0
1
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
0
1
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
1
0
EMPNO ENAME JOB
Figure5.5b
Reprsentation interne
d'un index bitmap.
N ligne 1 2 3 4 5 6 7 8 9 10 11 12 13 14
COMPTABLE 1 0 0 0 0 0 0 0 0 0 1 1 0 1
VENDEUR 0 1 1 0 1 0 0 0 0 1 0 0 0 0
PRESIDENT 0 0 0 0 0 0 0 0 1 0 0 0 0 0
MANAGER 0 0 0 1 0 1 1 0 0 0 0 0 0 0
INGENIEUR 0 0 0 0 0 0 0 1 0 0 0 0 1 0
COMPTABLE
OU
PRESIDENT 1 0 0 0 0 0 0 0 1 0 1 1 0 1
Index bitmap et oprations LMD
Il nest pas recommand dutiliser les index bitmap sur des tables trs mouvemen-
tes par des sessions concurrentes Cela peut poser des problmes de verrouillage
cause de la structure de stockage interne des RowID, laquelle permet dconomiser
de lespace. Ce sont des index plutt orients datawarehouse mais qui restent cepen-
dant tout fait utilisables dans des environnements OLTP modrs.
Index bitmap et valeurs nulles
Les index bitmap grent mieux les valeurs nulles que les index B*Tree puisque les
valeurs NULL sont considres comme des valeurs distinctes au mme titre que les
autres.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 103
Mise en uvre
La syntaxe de cration dun index bitmap est trs proche de celle dun index B*Tree,
il faut juste ajouter le mot cl bitmap. Ici aussi, il est possible de crer des index sur
fonction avec les index bitmap.
create bitmap index <Nom_Index> on <NomTable>(<col1>[,<col2>,]);
Les index bitmap prsentent lintrt dtre adapts lindexation de colonnes
ayant peu de valeurs distinctes. Cependant, un index bitmap employ sur une seule
colonne de faible slectivit ne sera pas beaucoup plus effcace quun index B*Tree.
Lavantage majeur des index bitmap apparat lors de la combinaison de conditions
sur des colonnes ayant chacune une faible slectivit mais qui, ensemble, auront
une forte slectivit. Sinon, on retrouve le problme des index B*Tree o le cot des
allers-retours entre lindex et le tas dpasse le gain apport par lindex.
Les index bitmap sont rputs pour tre adapts des colonnes ayant relativement
peu de valeurs distinctes. Cependant, les rsultats des tests ci-aprs montrent que,
mme avec 20millions de valeurs distinctes, ils ont de bonnes performances. Nan-
moins, ils occupent, dans ce cas, plus despace que des index B*Tree, alors que cest
gnralement le contraire. On constate que, sil y a peu de valeurs distinctes, ils ont
des tailles trs faibles par rapport aux index B*Tree, ce qui rendra leur manipulation
dautant plus effcace. Par contre, lorsque le nombre de valeurs distinctes augmente
( partir de un million de valeurs), on saperoit que la taille de lindex bitmap
explose. La taille dun index B*Tree est constante mais plus importante que celle
des index bitmap dans de nombreux cas puisque chacune de ses entres contient la
cl plus le RowID, contrairement aux index bitmap qui ont une technique de stockage
optimise.
Ci-aprs, on lit quelques rsultats de tests de performance montrant le bon com-
portement des index bitmap sur une table de 20 millions denregistrements avec
des colonnes indexes ayant de 2 20millions de valeurs distinctes. On y trouve le
temps ncessaire pour effectuer le calcul dune moyenne sur une colonne de la table
en fonction dun critre sur une colonne indexe ayant plus ou moins de valeurs
distinctes. Le test est fait avec un index bitmap, un index B*Tree et sans aucun
index. Ces tests ont t raliss avec des donnes ayant un trs bon facteur de foi-
sonnement, ce qui amliore un peu les choses, spcialement sur les tests ayant peu
de valeurs distinctes.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
104 tude et optimisation desrequtes Axe 2
Figure5.6a
volution de la taille
des index bitmap et
B*Tree en fonction
du nombre de valeurs
distinctes (chelle
logarithmique).
Taille Bitmap
4 Mo
4 Mo
5 Mo
5 Mo
5 Mo
10 Mo
63 Mo
576 Mo
Taille B*Tree
376 Mo
376 Mo
376 Mo
376 Mo
376 Mo
376 Mo
376 Mo
376 Mo
Nb de valeurs distinctes
2
20
200
2 000
20 000
200 000
2 000 000
20 000 000
1 000
Mo
100
10
1
2 0
2
0
2
0
0
2

0
0
0
2
0

0
0
0
2
0
0

0
0
0
2

0
0
0

0
0
0
2
0

0
0
0

0
0
0
Taille Index Bitmap Taille Index B*Tree
Figure5.6b
Temps de rponse
en fonction du nombre
de valeurs distinctes.
Temps Bitmap
20,500 s
0,719 s
0,078 s
0,015 s
0,015 s
0,015 s
0,015 s
0,015 s
Temps B*Tree
67,000 s
0,484 s
0,062 s
0,016 s
0,015 s
0,015 s
0,015 s
0,015 s
Nb de valeurs distinctes
2
20
200
2 000
20 000
200 000
2 000 000
20 000 000
Temps Sans Index
23,125 s
23,125 s
23,125 s
23,125 s
23,125 s
23,125 s
23,125 s
23,125 s
80
secondes
70
60
40
30
20
50
10
0
2 0
2
0
2
0
0
2

0
0
0
2
0

0
0
0
2
0
0

0
0
0
2

0
0
0

0
0
0
2
0

0
0
0

0
0
0
Temps Bitmap Temps Sans Index Temps B*Tree
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 105
Figure5.6c
Nombre de
Consistent Gets
en fonction du
nombre de valeurs
distinctes.
Consistent
Gets Bitmap
73 285
6 918
656
63
9
4
4
3
Consistent
Gets B*Tree
96 650
9 266
890
90
90
83
83
3
Nb de valeurs
distinctes
2
20
200
2 000
20 000
200 000
2 000 000
20 000 000
Consistent Gets
Sans Index
144 123
144 123
144 123
144 123
144 123
144 123
144 123
144 123
160 000
Consistent Gets
140 000
120 000
80 000
60 000
40 000
100 000
20 000
0
2 0
2
0
2
0
0
2

0
0
0
2
0

0
0
0
2
0
0

0
0
0
2

0
0
0

0
0
0
2
0

0
0
0

0
0
0
Gets Bitmap Gets Sans Index Gets B*Tree
valuation
valuons les diffrentes solutions pour fltrer plusieurs colonnes de faible cardina-
lit, sur une table de 2606477enregistrements avec des conditions sur la colonne
Nolivre ayant 2 972 valeurs distinctes et la colonne Remise ayant 3 valeurs
distinctes.
Nous allons comparer les diffrentes solutions avec la requte suivante:
select * from cmd_lignes where nolivre=6262 and remise=7
Sans aucun index, il faut parcourir toute la table do de nombreux Consistent Gets
(voir Figure5.7).
Avec 2 index B*Tree, le SGBDR convertit les rsultats des Range Scan en index
bitmap afn de les combiner (voir Figure5.8).
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
106 tude et optimisation desrequtes Axe 2
Figure5.7
Sans aucun index.
Figure5.8
Avec deux index B*Tree.
On voit donc que, dans certains cas, plusieurs B*Tree peuvent tre utiliss lors dun
mme accs une table, mais le cot li la conversion en index bitmap est lev.
En fait, dans cet exemple en particulier, loptimiseur avait choisi de nutiliser que
lindex sur Nolivre. Nous avons forc ce comportement afn de vous le prsenter.
create index IS_cmd_lignes_Livre on cmd_lignes(nolivre);
create index IS_cmd_lignes_Remise on cmd_lignes(Remise);
Si les index B*Tree ne sont pas conus pour tre combins, les index composites
grent parfaitement les conditions sur deux colonnes. Nous obtenons ainsi un bon
rsultat (voir Figure5.9).
create index IS_CMD_LIGNES_LIVREREMISE on CMD_LIGNES (nolivre, remise)
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 107
Lutilisation des index composites est trs effcaces lorsque les conditions des
requtes sappliquent exactement aux colonnes de lindex. Si les conditions peuvent
varier sur un ensemble de colonnes (par exemple une requte avec des conditions
sur Col1, Col2 et Col5, une deuxime requte sur Col2, Col3 et Col4, une troisime
requte sur Col1, Col3 et Col6), il faudrait crer autant dindex composites que de
combinaisons possibles entre les colonnes ce qui risquerait doccuper pas mal
despace de stockage et dimpacter les mises jour de la table.
Figure5.9
Avec index B*Tree
composite.
Avec les deux index bitmap suivants:
create bitmap index IS_cmd_lignes_Livre on cmd_lignes(nolivre);
create bitmap index IS_cmd_lignes_Remise on cmd_lignes(Remise);
Figure5.10
Avec deux index bitmap.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
108 tude et optimisation desrequtes Axe 2
On voit que les deux index bitmap sont naturellement combins (voir Figure5.10).
Cette solution est lgrement moins bonne que lindex B*Tree composite de cet
exemple mais, suivant les cas, la tendance peut sinverser. Ces deux solutions ont
souvent des performances comparables.
La solution avec les index bitmap allie performance, faible encombrement et fexi-
bilit des conditions.
Au Tableau5.1, nous voyons que les index bitmap sont plus petits.
Tableau5.1: Taille des diffrents index
Type index Taille index NoLivre Taille index Remise
Index bitmap 10Mo 0.88Mo
Index B*Tree 44Mo 39Mo
Index B*Tree composite 51Mo
5.2.5 Bitmap Join Index
Les Bitmap Join Index permettent de crer des index bitmap bass sur les valeurs
dune autre table avec laquelle on prvoit de faire une jointure. Dans lexemple
ci-aprs, nous crons un index dans la table cmd_lignes portant sur la colonne
Collection de la table livres. Ainsi, si nous effectuons une requte sur la table cmd_
lignes avec comme condition la colonne Collection, le SGBDR naura pas besoin
de faire la jointure avec la table livres, ce qui apportera un gain signifcatif. Ilfau-
dra cependant continuer crire cette jointure dans la requte:
create bitmap index is_cmd_lignes_collect on cmd_lignes(l.collection)
from cmd_lignes cl,livres l where cl.nolivre=l.nolivre;
Voici un exemple de requte tirant parti du Bitmap Join Index:
select sum(quantite) from cmd_lignes cl,livres l
where cl.nolivre=l.nolivre and l.collection='Best-sellers';
Ce type dindex est particulirement intressant si vous avez besoin de faire des
jointures uniquement pour appliquer des conditions par galit. Dans ce cas, il ny
aura plus besoin de faire la jointure, ce qui apportera un gain signifcatif. Par contre,
si la jointure reste ncessaire pour appliquer des conditions ou affcher les autres
champs, lindex sera moins intressant mais il pourra cependant toujours prsenter
un intrt, car il rduira la taille de lensemble joindre.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 109
Il faut bien garder lesprit quun Bitmap Join Index est avant tout un index bitmap,
cest--dire quil est conu pour les tests dgalit, quil est surtout recommand
pour un faible nombre de valeurs distinctes et quil nest pas adapt aux tables sou-
mises beaucoup de LMD concurrents.
Mise en uvre
La syntaxe dun Bitmap Join Index est la suivante:
create bitmap index <Nom_Index> on <NomTable>(<col1>[,<col2>,])
from <NomTable>,<NomTableJointe>
Where <JointureEntreLesTables> ;
valuation
Nous allons valuer les performances de cet objet avec la requte suivante:
select sum(quantite) from cmd_lignes cl,livres l
where cl.nolivre=l.nolivre and cl.remise=7 and l.collection='Programmeur'
Dans cette premire trace dexcution, il y a un index bitmap sur la colonne Remise
mais il nest pas utilis car une opration table access full est requise pour la
jointure.
Figure5.11
Trace d'excution sans
Bitmap Join Index.
Dans la deuxime trace dexcution (voir Figure 5.12), nous avons plac un Bit-
map Join Index sur le champ Collection (voir exemple prcdent). Nous voyons que
loptimiseur nestime plus ncessaire de faire une jointure avec la table livre pour
rpondre cette requte (alors que celle-ci est prsente dans la requte). En cons-
quence, les deux index bitmap sont combins ce qui est particulirement effcace.
Les Consistent Gets sont diviss par 180 et le temps dexcution par10.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
110 tude et optimisation desrequtes Axe 2
Figure5.12
Trace d'excution avec
un Bitmap Join Index.
Dans la troisime trace dexcution (voir Figure 5.13), nous avons plac des index
bitmap sur Remise et Nolivre mais supprim le Bitmap Join Index. Nous constatons
une jointure par boucle imbrique sur lindex bitmap de la colonne Nolivre qui est
combine au fltrage bitmap sur la colonne remise. Les performances sont moindres
quavec le Bitmap Join Index mais cependant acceptables. Si lindex sur la colonne
Nolivre avait t de type B*Tree, le plan aurait t quasiment le mme car le rsultat
du Range Scan de lindex B*Tree aurait t converti en bitmap.
Figure5.13
Trace d'excution sans
Bitmap Join Index mais
avec des index bitmap
sur NoLivre et Remise.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 111
MS SQL Server et MySQL
Ni SQL Server, ni MySQL ne proposent d'index bitmap ou de Bitmap Join Index.
5.2.6 Full Text Index
En SQL de base, pour chercher un texte dans une chane de caractres, on crit
quelque chose comme ceci:
select count(*) from texteslivres where texte like '%voyage%';
Cest simple comprendre mais ce nest pas trs effcace sur des textes un peu
importants. De plus, si le texte est dans un champ de type CLOB, les performances
scroulent cause des accs au segment LOB qui est spar du tas. Le principal
problme de cette requte est quelle ne peut utiliser aucun index B*Tree car la
prsence de like %... est un cas disqualifant pour lusage des index.
Nous allons regarder comment optimiser ce type de requte, mais nous avons besoin
dabord dune base de donnes avec un peu de texte. Pour cela, nous nous rendons
sur le site http://www.livrespourtous.com et nous rcuprons quelques livres de
Victor Hugo et dmile Zola, nous dcoupons approximativement les pages et nous
les chargeons dans la table ci-aprs. Afn daugmenter un peu le volume, nous dupli-
quons ces donnes en cinq exemplaires, ce qui nous permet davoir une table de
17325enregistrements pour une taille de 40Mo. Cette base est disponible sur le site
de lauteur, ladresse http://www.altidev.com/livres.php.
create table TextesLivres(
ID NUMBER,
Auteur varchar2(100),
Titre varchar2(100),
SousTitre varchar2(100),
TEXTE CLOB,
constraint PK_TextesLivres primary key (ID) );
insert into texteslivres select id+10000, auteur, titre, soustitre||' Bis',
texte from texteslivres where id <5000 order by 1;
insert into texteslivres select id+20000, auteur, titre, soustitre||' Ter',
texte from texteslivres where id <5000 order by 1;
insert into texteslivres select id+30000, auteur, titre, soustitre||'
Quater', texte from texteslivres where id <5000 order by 1;
insert into texteslivres select id+40000, auteur, titre, soustitre||'
quinquies', texte from texteslivres where id <5000 order by 1;
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
112 tude et optimisation desrequtes Axe 2
La requte suivante a un temps dexcution de 2,75 secondes et ncessite
5144Consistent Gets.
select count(*) from texteslivres where texte like '%voyage%';
La variante de cette requte utilisant la fonction UPPER a un temps dexcution de
2,92secondes et ncessite 22999Consistent Gets.
select count(*) from texteslivres where upper(texte) like '%VOYAGE%'
Si les textes sont suprieurs 4000caractres, ils sont stocks dans un segment
spar (voir la section 5.3.1 pour plus de dtails), ce qui va encore plus pnaliser
ce genre de requte. Dans notre cas, seulement 0,4 % des enregistrements dpas-
sent cette limite. Mais si nous modifons les paramtres de la table avec la clause
DISABLE STORAGE IN ROW, qui permet de forcer le stockage systmatique dans un
segment spar, alors notre requte a un temps dexcution de 17secondes et nces-
site 111632Consistent Gets.
Maintenant que nous avons mis en vidence que loprateur LIKE nest pas une solu-
tion trs performante pour effectuer des recherches dans des champs texte, voyons
les solutions possibles. Oracle met notre disposition des outils qui sont adapts
ces problmatiques au moyen dindex spcifques de domaine. Je vous conseille
de consulter le document Oracle Text Application Developers Guide dans la docu-
mentation Oracle pour avoir des informations dtailles. Nous tudierons ici les
lments cls qui permettent doptimiser les requtes de type Full Text Search de
plus en plus prises avec lavnement du Web et de Google.
Oracle Text met disposition des index adapts aux recherches de textes. Ils sont
capables de travailler sur des champs texte mais aussi sur des champs de type
BLOB contenant des fchiers bureautiques. La phase dindexation utilise un fltre
qui convertit les documents (word, pdf, etc.) en texte et un analyseur lexical (lexer)
qui fait une analyse lexicale du texte afn den extraire les mots (ainsi, les recherches
se font au niveau des mots et non pas sur des morceaux de chanes contrairement
aux recherches laide du prdicat like %chane%). Lanalyseur lexical peut aussi
convertir les caractres en majuscules (par dfaut) et les signes diacritiques (carac-
tres accentus, trma, etc.) en leurs caractres de base afn de faire correspondre les
recherches avec ou sans accents (dsactiv par dfaut).
Plusieurs types dindex sont notre disposition, chacun orient vers un
usageparticulier:
CONTEXT. Adapt aux recherches de mots dans des grands champs texte ou des
documents. Ce type dindex extrait tous les mots des documents, les compte et
les associe aux enregistrements concerns. Les mots ne sont donc pas rpts, ce
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 113
qui permet davoir frquemment un index plus petit que le texte original. Ce type
dindex doit, par dfaut, tre synchronis manuellement.
CTXCAT. Adapt pour indexer de petits textes en les combinant avec des champs
structurs afn de faire des recherches combines plus effcaces. Il occupe pas
mal de place et peut dpasser largement la taille du texte initial. Il nest donc
pas adapt lindexation de grands textes. Ce type dindex est synchronis
automatiquement.
CTXRULE. Permet de classifer les documents suivant leur contenu partir de
loprateur MATCHES.
CTXXPATH. Adapt lindexation des documents XML.
Pour des recherches Full Text sur des champs volumineux comme dans notre
exemple, il est donc recommand dutiliser un index de type CONTEXT.
Mise en uvre d'un index CONTEXT
La syntaxe de base permettant de crer un index Full Text de type CONTEXT est la
suivante:
create index <NomIndex> on <NomTable>(<colonnes>) indextype is CTXSYS.CONTEXT;
Ci-aprs, vous voyez un exemple de cration dun index o une conversion des
signes diacritiques en caractres de base est spcife. La premire tape consiste
crer des prfrences pour le lexer. Elle est ncessaire une seule fois pour lensemble
des index partageant les mmes prfrences de lexer. La seconde tape vise la cra-
tion de lindex lui-mme, en spcifant le type CONTEXT et les ventuels paramtres.
begin
ctx_ddl.create_preference('mylex', 'BASIC_LEXER');
ctx_ddl.set_attribute ( 'mylex', 'base_letter', 'YES');
end;
create index IS_FT_TEXTESLIVRES on TEXTESLIVRES(texte)
indextype is CTXSYS.CONTEXT parameters ( 'LEXER mylex' );
la suite de la cration de lindex, les tables suivantes sont cres : dr$is_ft_
texteslivres$i, dr$is_ft_texteslivres$k, dr$is_ft_texteslivres$n, dr$is_
ft_texteslivres$r. Dans lexemple, elles occupent 20 Mo alors que notre table
occupe 40Mo. Si nous regardons de plus prs la table dr$is_ft_texteslivres$i,
nous constatons quelle contient chaque mot converti en majuscules et sans signes
diacritiques, ainsi que le nombre doccurrences de chaque mot.
Maintenant que les donnes sont indexes, nous pouvons faire des recherches
laide de loprateur CONTAINS (cet oprateur nest oprationnel que si un index
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
114 tude et optimisation desrequtes Axe 2
textuel est prsent). Comme nous le voyons dans lexemple suivant, nous avons
notre disposition la fonction SCORE qui donne un score de pertinence de la rponse.
SELECT SCORE(1) score,id FROM texteslivres
WHERE CONTAINS(texte, 'voyage', 1) > 0
ORDER BY SCORE(1) DESC;
Cette requte ne retourne plus que 310 enregistrements, alors que la prcdente,
implmente avec un prdicat LIKE, en annonait 680. Cela vient juste du fait que la
version avec like %voyage% considre aussi les valeurs suivantes: voyageaient,
voyageait, voyageant, voyager, voyagera, voyages, voyageur, voyageurs, voyageuse,
voyageuses alors que loprateur CONTAINS lui travaille sur les mots et fait donc la
diffrence entre les mots voyage et voyager.
Pour chercher plusieurs mots, il ne faut pas utiliser un oprateur AND dans la clause
WHERE mais la syntaxe & de loprateur CONTAINS comme dans lexemple ci-aprs,
qui recherche les textes contenant les mots "voyage" et "soleil".
SELECT count(*) FROM texteslivres
WHERE CONTAINS(texte, 'voyage & soleil', 1) > 0
Loprateur CONTAINS gre lui tout seul tout un langage de requte texte. Consultez
la documentation de rfrence Oracle Text pour avoir plus de dtails sur les possi-
bilits de cet oprateur. On peut, par exemple, faire des recherches foues, des com-
binaisons, utiliser des thesaurus, des proximits de mots, etc. La requte ci-aprs
trouvera les textes avec les mots proches de "voyage" tels que "voyageur" et exclura
le mot "voyage" avec loprateur~.
SELECT * FROM texteslivres
WHERE CONTAINS(texte, 'fuzzy(voyage) ~voyage', 1) > 0
Si on compare la solution avec loprateur LIKE prcdemment teste, la requte
suivante prend 0,172seconde et ncessite 1165Consistent Gets.
SELECT count(*) FROM texteslivres WHERE CONTAINS(texte, 'voyage', 1) > 0
Certes, cest beaucoup pour un index mais cela reste en trs net progrs puisque nous
avons divis le temps dexcution par 16 par rapport la solution initiale et mme par
100 par rapport la version qui utilisait un stockage dans un segment LOB spar.
Bien que les index de type CONTEXT ne soient pas synchroniss automatiquement
avec les donnes, leur mise jour est incrmentale. Il faut utiliser la commande
suivante pour excuter une synchronisation de lindex avec les donnes:
EXEC CTX_DDL.SYNC_INDEX('IS_FT_TEXTESLIVRES');
Il est cependant possible de spcifer dans le CREATE INDEX des clauses de rafrachis-
sement automatique lors de la cration de lindex:
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 115
SYNC(MANUAL |EVERY "interval-string" |ON COMMIT)
Au fur et mesure que lindex grandit avec les synchronisations, il se fragmente, on
doit donc rgulirement loptimiser. Durant cette opration, dans sa version rapide
(Fast), les entres dindex associes des enregistrements qui ont t supprims
ou qui ne sont plus dans lenregistrement ne sont pas automatiquement effaces.
Ilfaut, pour traiter ces cas-l, effectuer une optimisation complte afn de les purger
(remplacer FAST par FULL ci-aprs).
EXEC CTX_DDL.OPTIMIZE_INDEX('IS_FT_TEXTESLIVRES','FAST');
Mise en uvre d'un index CTXCAT
Les index CTXCAT sont adapts lexcution de requtes combinant une recherche
Full Text avec des critres sur les autres colonnes de lenregistrement. Ce type de
requte est possible avec les index CONTEXT: il sufft de mettre les deux prdicats
dans la requte. Cependant, cette solution ncessite de parcourir dabord lindex
CONTEXT puis daller vrifer les autres prdicats pour chaque enregistrement. Cela
risque dtre peu effcace si les autres prdicats portant sur les champs de la table
sont trs slectifs.
Lindex CTXCAT, comme lindex CONTEXT isole les mots. En plus, pour chaque enre-
gistrement, il stocke aussi les valeurs des autres champs qui sont mentionns lors de
sa cration pour pouvoir faire des recherches combines. Si le rsultat est assez eff-
cace, lespace occup est particulirement important puisque chaque mot est stock
avec les valeurs des autres champs de lindex.
Comme nous lavons dit prcdemment, ces index ne sont pas adapts lindexa-
tion de textes volumineux. Nous allons donc prendre comme exemple le champ
Adresse de la table clients de notre base exemple et le combiner au champ Pays,
puis comparer les performances sur le domaine des recherches combines.
cette fn, nous crons un index de type CTXCAT intgrant la colonne Pays de la table
clients:
EXEC CTX_DDL.CREATE_INDEX_SET('ISET_IS_CLIENT_ADRESSE_PAYS');
EXEC CTX_DDL.ADD_INDEX('ISET_IS_CLIENT_ADRESSE_PAYS','PAYS');
CREATE INDEX IS_CLIENT_ADRESSE_PAYS ON CLIENTS(Adresse1)
INDEXTYPE IS CTXSYS.CTXCAT PARAMETERS ('index set ISET_IS_CLIENT_ADRESSE_PAYS');
La requte suivante sexcute en 0,015seconde et ncessite 4Consistent Gets:
select * from clients t where CATSEARCH(adresse1,'FOREST',
'pays = ''Japan''')> 0;
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
116 tude et optimisation desrequtes Axe 2
alors que lquivalent, avec un index de type CONTEXT et loprateur CONTAINS com-
bin une clause WHERE, sexcute en 0,016 seconde et ncessite 130 Consistent
Gets. Lquivalent avec un prdicat LIKE sexcute en 0,016seconde et ncessite
628Consistent Gets. Le temps dexcution nest pas trs signifcatif tant donn le
faible volume, mais le nombre de Consistent Gets est parlant: entre la solution la
plus lente et la plus rapide, il y a un ratio de 150. Cependant, le prix payer pour
lindex CTXCAT est de 18Mo alors que la table occupe seulement 5Mo. Le cot de
lindex CONTEXT est lui de 1,3Mo.
Ci-dessous les instructions permettant deffectuer le test utilisant un index CONTEXT :
CREATE INDEX IS_FT_CLIENTS_ADRESSE1 ON CLIENTS(ADRESSE1) INDEXTYPE IS CTXSYS.
CONTEXT parameters ( 'LEXER mylex' );
select * from clients
where CONTAINS(adresse1, 'FOREST', 1) > 0 and pays='Japan';
Ci-dessous les instructions permettant deffectuer le test nutilisant aucun index:
select * from clients
where upper(adresse1) like '%FOREST%' and pays='Japan'
MS SQL Server
Sous SQL Server, la fonctionnalit de recherche Full Text est dlgue des services ex-
ternes la base de donnes (Msftesql.exe et Msftefd.exe), de ce fait, les index Full Text ne
sont pas dans la base de donnes. La fonctionnalit doit tre active pour chaque base de
donnes soit dans SQL Server Management Studio, dans l'onglet Fichier des proprits de
la base de donnes, soit avec l'instruction suivante:
EXEC sp_fulltext_database @action = 'enable'
Il faut ensuite crer un catalogue, qui pourra tre utilis pour plusieurs tables. Cepen-
dant, pour indexer de gros volumes, il sera pertinent de crer des catalogues indpen-
dants pour chaque table. L'instruction Create Fulltext Catalog permet de crer le
catalogue en spcifant les options de gestion des caractres diacritiques ainsi que l'em-
placement des fchiers d'index sur le disque dur:
CREATE FULLTEXT CATALOG MonCatalogueFT as default
Il ne sera possible de crer qu'un seul index par table qui contiendra l'ensemble des
colonnes indexer:
Create Fulltext Index on texteslivres (texte)
KEY INDEX PK_TextesLivres WITH CHANGE_TRACKING AUTO
Create Fulltext Index on <NomDeLaTable>(<Colonnes, >)
KEY INDEX <ClePrimaireOuAutreIndexUnique>
WITH CHANGE_TRACKING <OptionsDeMiseAJour>
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 117
Ensuite, il est possible de faire des recherches Full Text avec diffrents oprateurs. L'op-
rateur CONTAINS permet de faire des recherches de termes simples en les combinant
ventuellement avec des oprateurs boolens (AND, AND NOT, OR). Il intgre aussi la
notion de prfxe "voyage*", les notions d'infexion FORMSOF ( INFLECTIONAL ,voyage)
et de synonymes au moyen d'un thesaurus.
select count(*) from texteslivres where CONTAINS(texte, 'voyage')
La fonction CONTAINSTABLE est une variante de CONTAINS qui permet de retourner une
table deux colonnes contenant la cl de l'index (Key) et le classement par pertinence
(Rank) :
select * from CONTAINSTABLE(texteslivres,texte, 'voyage')
L'oprateur FREETEXT permet de faire une recherche analogue CONTAINS en incluant
les infexions et les synonymes mais avec une syntaxe plus simple puisqu'il sufft de spci-
fer la liste de mots recherchs:
select * from texteslivres where FREETEXT(texte, 'voyage train')
La fonction FREETEXTTABLE retourne une table comme CONTAINSTABLE mais avec la syn-
taxe de FREETEXT.
MySQL
MySQL intgre aussi un mcanisme de recherche Full Text mais seul le moteur MyISAM in-
tgre un index spcialis permettant d'avoir de meilleurs rsultats. Ci-aprs, un exemple
de cration d'index et de recherche est prsent:
Create FULLTEXT index IS_FT_TEXTESLIVRES ON TEXTESLIVRES(texte);
SELECT * FROM texteslivres WHERE match(texte) against ('voyage')
Les recherches sont faites, par dfaut, en mode langage naturel mais il est possible de
travailler en mode boolen. La requte suivante recherche les enregistrements avec le
mot "voyage" mais sans le mot "voyageur". Le signe plus (+) exige la prsence du mot,
le signe moins () exige son absence, sinon la prsence est optionnelle mais augmente la
pertinence. L'oprateur* permet de faire des recherches sur le dbut d'un mot (voyag*),
> et < donnent plus ou moins d'importance certains mots, les guillemets servent cher-
cher des correspondances exactes sur des phrases.
SELECT * FROM texteslivres WHERE match(texte) against ('+voyage
voyages -voyageur' in BOOLEAN mode)
Par dfaut, le rsultat est tri par pertinence. Tout comme sous Oracle, il est possible de
crer un index sur plusieurs colonnes et d'effectuer une recherche simultanment sur
plusieurs colonnes.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
118 tude et optimisation desrequtes Axe 2
5.3 Travail autour des tables
5.3.1 Paramtres de table
PCTFree = 0
travers la clause de stockage et le paramtre PCTFREE (valant 10% sil est omis),
le SGBDR rserve lors des insertions de donnes PCTFree % despace dans chaque
bloc pour agrandir les donnes sans devoir faire de migration de ligne (row migration)
lors des UPDATE qui auront peut-tre lieu dans le futur.
Certaines tables contiennent des donnes dont les enregistrements ne grossiront
jamais, lespace rserv par loption PCTFREE est donc perdu. De plus, il entranera
lusage de PCTFree% blocs supplmentaires pour stocker le mme nombre den-
registrements que si le paramtre tait 0%. Cela augmentera donc le nombre de
Consistent Gets et rduira les performances dautant.
Sur les tables qui ont des lignes qui ne varient pas en taille, il est donc pertinent de
spcifer le paramtre PCTFREE 0 dans la clause de stockage.
Create table xxx ( . . . ) PCTFREE 0;
Rpartition des tablespaces
Pour chaque objet, il est possible de dfnir un tablespace spcifque. Si cette clause
est omise, cest le tablespace par dfaut de lutilisateur qui est choisi. Il sera donc le
mme pour tous les objets qui nont pas spcif de tablespace.
Si vous disposez de plusieurs disques (ou ensembles de disques), vous avez tout int-
rt dfnir des tablespaces propres chacun des disques. Ainsi, vous pourrez rpar-
tir les objets qui travaillent simultanment et qui causent des Physical Reads sur
des disques diffrents et ainsi cumuler les bandes passantes des diffrents disques.
Chaque tablespace est compos de datafles. Ces fchiers peuvent tre rpartis sur dif-
frents disques, mais il faut penser quon na aucun moyen dinfuer sur la rpartition
des objets dans les datafles. Donc, si vous souhaitez matriser cette rpartition, crez
plutt des tablespaces avec des datafles sur un seul disque ou groupe de disques.
Create table xxx ( . . . ) TABLESPACE NomDuTablespace;
MS SQL Server
Sous SQL Server, la mme logique est applicable, sauf qu'on parlera de legroup la place
de tablespace. De la mme faon, il est possible d'affecter chaque objet un legroup.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 119
MySQL
Avec le moteur MyISAM, vous pouvez spcifer les options DATA DIRECTORY et INDEX DI-
RECTORY pour chaque table et ainsi rpartir vos tables sous diffrents disques.
Avec le moteur InnoDB, par dfaut, il n'y a qu'un seul tablespace qui peut tre constitu
de plusieurs fchiers rpartis sur plusieurs disques mais, de la mme faon que sous Oracle
avec les datafles, vous ne pouvez pas infuer sur la rpartition des donnes dans les f-
chiers. L'option INNODB_FILE_PER_TABLE permet d'avoir un tablespace par table mais elle
ne permet pas de les rpartir sur plusieurs volumes.
Compression de table
Cette option permet de compresser les doublons prsents dans les blocs. On devrait
dailleurs parler plutt de "dduplication" que de "compression", car ce terme fait
penser, tort, lusage dalgorithmes de compression, tels que Lempel-Ziv. Cepen-
dant, la dduplication a lavantage dtre mieux adapte lusage dans une base de
donnes.
Le principe est de compresser les donnes au sein dun bloc. Les donnes identiques
du bloc sont rpertories dans un dictionnaire au dbut du bloc. De ce fait, chaque
occurrence des donnes contient seulement une rfrence lentre dans le dic-
tionnaire au lieu de la donne. Le dictionnaire est uniquement constitu de valeurs
entires: ainsi, les donnes "Navarro Laurent" et "Laurent Navarro" ne seront pas
compresses car elles sont, certes, composes de parties identiques mais elles sont
des valeurs diffrentes. De fait, la compression sera gnralement inoprante pour
compresser des champs de taille importante.
La compression sactive avec loption COMPRESS dans la clause de stockage de la
table et elle nest disponible que sur les tables organises en tas (pas sur les IOT que
nous tudierons un peu plus loin). COMPRESS fait rfrence la compression de base,
qui a t introduite dans la version 9i sous le nom de DSS table compression. Ce
type ne compresse que les donnes insres en direct path (via sql*loader en mode
direct path ou avec le hint APPEND. Voir Chapitre 7, section 7.3.9, "Insertion en mode
Direct path").
La version11g Release1 a introduit COMPRESS FOR ALL OPERATION, qui a t rem-
place dans la version11g Release2 par COMPRESS FOR OLTP. Cette option permet
dappliquer la compression toutes les oprations; elle est prsent recommande
pour un usage en environnement OLTP.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
120 tude et optimisation desrequtes Axe 2
La compression de table introduit quelques restrictions, telles quun nombre de
colonnes infrieur 255, et surtout des limites sur la suppression de colonnes.
Sur notre table exemple, cmd_lignes, nous obtenons une rduction de lespace de
25 %. En termes de performances sur une requte ncessitant un Full Table Scan
dune grosse table, ce qui demande donc des Physical Reads, nous constatons un
gain de lordre de 30%. En criture, les performances sont assez bonnes aussi, car
la surcharge CPU est gnralement compense par la rduction des entres/sorties.
Le seul cas qui semble tre plus frquemment dfavorable la compression est
lutilisation dUPDATE. Cette technique ne sera donc pas trs adapte des tables qui
subissent de trs nombreuses modifcations denregistrements.
La version11g Release2 a revu compltement la syntaxe des options de compres-
sion. Ces changements sont rsums au Tableau5.2.
Create table xxx ( . . . ) COMPRESS;
Tableau5.2: Options de compression des diffrentes versions d'Oracle
Syntaxe 11g Release 2 Syntaxe 11g Release 1 Syntaxe 10g et 9i
COMPRESS ou COMPRESS BASIC COMPRESS ou COMPRESS FOR
DIRECT_LOAD OPERATION
COMPRESS
COMPRESS FOR OLTP COMPRESS FOR ALL OPERATION
Non disponible
COMPRESS FOR QUERY
et COMPRESS FOR ARCHIVE
Nouvelles options11g Release2
ncessitant le moteur Exabyte
MS SQL Server
La version2008, dans ses ditions Entreprise et Dveloppeur, a introduit deux notions de
compression: la compression de ligne et la compression de page.
La compression de ligne est un mcanisme qui optimise l'espace requis pour le stockage
des types de taille fxe.
La compression de page travaille au niveau de la page. Cette technique recherche les va-
leurs ayant le mme dbut et les doublons afn de les stocker dans un dictionnaire. Cette
mthode est comparable celle d'Oracle, hormis le fait qu'elle travaille, en plus, sur les
dbuts des valeurs et pas seulement sur les valeurs entires.
La compression des donnes s'active l'aide de l'option de table DATA_COMPRESSION avec
les options suivantes:
DATA_COMPRESSION = { NONE | ROW | PAGE }
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 121
Gestion des LOB
Les LOB (Large Object correspondant aux types CLOB et BLOB) sont stocks dans
un segment spar de celui du tas. Cependant, par dfaut, la clause ENABLE STORAGE
IN ROW est active. De ce fait, les LOB dune taille infrieure 4Ko sont stocks
avec le reste de lenregistrement, alors que les LOB plus gros sont stocks dans le
segment spar.
Cela risque de ralentir les Table Scan ne ncessitant pas les donnes LOB car il y a
plus de blocs lire que si les donnes LOB taient toutes dans un segment spar.
Toutefois, ce mode de stockage permet dacclrer la rcupration des enregistre-
ments avec des petits LOB en vitant les accs supplmentaires au segment LOB.
Selon le type daccs dont vous avez besoin, il faudra choisir le mode le plus adapt.
Si vous ne rcuprez jamais les LOB dans les Table Scan mais seulement en accs
monoenregistrement, il sera peut-tre pertinent de les stocker sparment. Laisser
le stockage des petits LOB activ en ligne a pour effet dagrandir la zone tas de la
table. Par contre, cela vite des va-et-vient entre le tas et le segment LOB pour les
petites donnes contenues dans les champs LOB.
Pour spcifer cette option, il faut ajouter dans la clause STORAGE de la table:
lob (<LeChampLob>) store as <NomDuSegment> (disable storage in row CHUNK 8K);
NomDuSegment est le nom du segment qui contiendra idalement le nom de la table
et du champ, par exemple SegLob_Matable_Monchamp. Le paramtre CHUNK contient
la taille utilise pour les allocations despace LOB pour une donne dans le segment
LOB. Cette valeur est forcment un multiple de la taille du bloc (8Ko par dfaut).
Pour des fchiers, la taille initiale de 8Ko et le fait de dsactiver le stockage en ligne
sont adapts, alors que pour des champs CLOB qui sont des champs texte poten-
tiellement gros, ce choix nest pas toujours judicieux. Cela entranera la cration de
beaucoup de blocs de 8Ko, pleins de vide, pour rien si ce sont des petites chanes.
Ayez bien conscience que si vous dsactivez le stockage en ligne, un CLOB de
10caractres occupera 8Ko.
Compression des LOB
La version 11g Release 1 a introduit la notion de SecureFiles pour stocker les
champs LOB. Une des options intressantes du point de vue de loptimisation est
la compression des champs LOB. Compltement transparente, elle a seulement un
impact sur les performances, surtout lors des oprations dcriture. Elle nest adap-
te que pour des donnes qui se compressent bien. Il est donc sans intrt dactiver
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
122 tude et optimisation desrequtes Axe 2
la compression dun LOB destin stocker des formats dj compresss (JPEG,
MPEG, ZIP, Audio,etc.).
lob (<LeChampLob>) store as <NomDuSegment> (compress [ HIGH | MEDIUM | LOW ]);
Sur notre table exemple, contenant des pages de livres, nous obtenons un gain des-
pace de 30%. Le parcours squentiel du champ LOB sur plusieurs enregistrements
est en toute logique pnalis, mais ce nest gnralement pas lopration la plus fr-
quente sur ce type de champ. En revanche, la recherche via un index Full Text nest,
en toute logique, pas du tout affecte puisque seul lindex est utilis. Dans ce cas-l,
seule la manipulation des LOB est impacte.
SecureFiles met aussi disposition une fonction de dduplication de donnes
laide de loption DEDUPLICATE. Celle-ci entrane, elle aussi, une surcharge signi-
fcative mais seulement en criture. Elle peut ventuellement tre intressante si
vos donnes sy prtent, cest--dire si plusieurs enregistrements contiennent exac-
tement la mme valeur. Sur la table exemple livres, qui contient les donnes en
quatre exemplaires, cela fonctionne bien, mais il semble que cette option ait pour
effet de dsactiver le stockage en ligne, ce qui, dans notre cas, est pnalisant.
5.3.2 Index Organized Table
Pour rappel, la structure dune table classique organise en tas (heap) ou HOT (Heap
Organized Table) utilisant des index B*Tree est la suivante(voir Figure 5.14a).
Les IOT (Index Organized Table) ont une organisation sensiblement diffrente
puisquelles intgrent les donnes dans lindex de cl primaire (voir Figure 5.14b).
Sur une table organise en tas, le tas et la cl primaire sont deux objets distincts alors
que sur une table de type IOT, ils sont confondus.
Cette organisation prsente les avantages suivants:
Gain despace. Il nest plus ncessaire:
de dupliquer les donnes de la cl primaire entre le tas et l'index;
de stocker les RowID permettant de faire le lien entre l'index B*Tree et le tas.
Gain en possibilit dusage de lindex. Au-del de 5% de la table parcourir,
on estime quil nest plus intressant dutiliser un index classique cause des
va-et-vient entre lui et le tas. Cette rgle ne sapplique pas de la mme faon aux
IOT, qui nont pas ces problmes puisque lindex de cl primaire et les donnes
sont confondus.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 123
Bloc Racine
Root Blocks
Blocs Branche
Branch Blocks
Blocs Feuille
Leaf Blocks
Le RowID permet de pointer sur les lignes stockes dans le Tas
Table Heap :
Donnes non ordonnes
20 000
50 000

150 000
240 000
1 000
2 000

15 000
16 000
0
1

998
999
ROWID
ROWID
ROWID
ROWID
1 000
1 015

1 700
1 900
ROWID
ROWID
ROWID
ROWID
20 000
21 000

35 000
47 000

4 521
582

874
1 015
LECLERC
DUPOND

ROCHE
BERTHIER
OPRATEUR
COMMERCIAL

COMMERCIAL
MANAGER

2 586
325

1
999
MARTIN
GUY

BERGER
LEGRAND
COMMERCIAL
MANAGER

COMMERCIAL
MANAGER

Figure5.14a
Table Heap et un index.
Figure5.14b
Structure d'une table IOT
Bloc Racine
Root Blocks
Blocs Branche
Branch Blocks
Les donnes sont dans
les feuilles du B*Tree
Blocs Feuille
Leaf Blocks
20 000
50 000

150 000
240 000
1 000
2 000

15 000
16 000
20 000
21 000

35 000
47 000

0
1

998
999
DUPONT
BERGER

MEUNIER
LEGRAND
COMPTABLE
COMMERCIAL

COMMERCIAL
MANAGER

1 000
1 015

1 700
1 900
DUPIC
BERTHIER

DUVAL
NEUVILLE
COMMERCIAL
MANAGER

MANAGER
ACHETEUR

Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
124 tude et optimisation desrequtes Axe 2
Toute mdaille ayant son revers, voil les principaux inconvnients des IOT:
La modifcation des valeurs de la cl primaire ou linsertion non squentielle pro-
voquent des mouvements de donnes plus importants puisque cela peut conduire
dplacer des lignes et non pas juste des cls dans des index.
Les index secondaires ncessitent plus despace (voir ci-aprs la section "index
B*Tree et IOT").
Les cas o le parcours seul de lindex de cl primaire rpond la demande seront
moins performants car, prsent, parcourir lindex de cl primaire revient par-
courir la table, ce qui se traduira gnralement par plus de donnes manipuler.
Mise en uvre
La dclaration dune table organise en index (IOT) se fait, dans le CREATE TABLE,
par la spcifcation de lorganisation INDEX (au lieu de HEAP par dfaut). Il nest pas
possible de convertir une table HOT en IOT et vice versa.
Create table xxx ( . . . ) ORGANIZATION INDEX;
Index B*Tree et IOT
Sur une table de type IOT, la cl primaire est intgre, mais il est cependant possible
de crer des index secondaires sur dautres colonnes, comme sur les tables organises
en tas. Ces index seront dune nature un peu diffrente.
Les index B*Tree contiennent habituellement, pour chaque entre, la cl de lindex
plus le RowID pointant sur une position dans le tas. Cependant, il existe une diff-
rence majeure entre les deux formats de table: sur celles organises en tas, les lignes
ne bougent pas dans le tas, alors que sur celles de type IOT, elles peuvent tre dpla-
ces car elles doivent respecter lordre de la cl primaire. Cela signife que lemploi
dun RowID pour dsigner les enregistrements sur les index secondaires des tables
de type IOT est dlicat. On ne peut pas envisager de mettre jour tous les index
chaque mouvement de ligne. Il faudrait pour cela retrouver et modifer les entres
correspondantes dans tous les index, ce qui serait particulirement pnalisant.
Donc, les index B*Tree sur IOT ne contiennent pas de RowID pour retrouver la
ligne pointe mais un Logical RowID plus la cl primaire. Le Logical RowID est le
numro du bloc dans lequel tait la ligne au moment de linsertion. Cest donc len-
droit o elle devrait toujours tre, puisquon suppose dans un IOT que les donnes
sont insres squentiellement. Cependant, au cas o lenregistrement aurait boug,
on utiliserait les donnes de la cl primaire places dans lindex pour retrouver len-
registrement en parcourant le B*Tree de la table.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 125
Les index B*Tree sur IOT contiennent la cl de lindex, Logical RowID linsertion
et la cl primaire. Ils sont donc plus gros que les index sur les tables organises en tas.
Cest dautant plus vrai que la cl primaire sera grosse. On veillera ne pas avoir trop
dindex secondaires sur les tables IOT qui nont pas une cl primaire de petite taille.
De plus, si la table est mouvemente et que cela conduise des dplacements den-
registrements dans dautres blocs, le Logical RowID contenu dans lindex conduira
souvent au mauvais bloc. Il faudra alors parcourir le B*Tree de la cl primaire pour
trouver lenregistrement demand, ce qui provoquera inutilement quelques oprations
supplmentaires. Ce type de problme ne fera quaugmenter au fl du temps car il
y aura de plus en plus de dplacements denregistrements. Une reconstruction de
lindex permettra de refaire pointer les Logical RowID sur les blocs adquats.
Index bitmap et IOT
Pour mettre en uvre un index bitmap sur un IOT, il faut que la table possde une
table de mapping, spcifant les paramtres suivants lors de la cration de la table:
ORGANIZATION INDEX MAPPING TABLE
Impact sur les oprations LMD
Lorganisation IOT des tables est un peu moins performante que lorganisation en
tas si on insre des donnes de faon non linaire par rapport la cl primaire.
Cependant, mme dans ce cas, ce nest pas dsastreux au moment de linsertion
car elle a lieu dans un B*Tree. Par contre, cela risque de provoquer des dplace-
ments denregistrements et, du coup, leffet sera peut-tre plus notable sur les don-
nes existantes car les index secondaires auront des Logical RowID errons, ce qui
entranera des accs supplmentaires lors des requtes SELECT.
la suite de nombreuses mises jour sur les cls ou dinsertions non squentielles,
des "trous" peuvent apparatre dans la table. Il sera alors peut-tre judicieux de la
rorganiser afn de la compacter.
ALTER TABLE clients_iot MOVE ONLINE;
Tableau5.3: Comparaison des temps de mise jour des cls de 30% de la table
Paramtre Table HEAP Table IOT
Temps 0,89s 6,047s
Consistent Gets 322 21918
CPU 39 201
update clients set NOCLIENT=NOCLIENT+1000000 where pays='USA'
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
126 tude et optimisation desrequtes Axe 2
Avant sa mise jour, la table clients en organisation IOT occupait 6144Ko, aprs,
elle occupe 8192Ko. Cela est li au fait que les enregistrements ont t dplacs de
leurs feuilles existantes pour aller dans de nouvelles feuilles. La plus grande valeur
tait 145000 avant la mise jour et celle-ci a dplac les enregistrements modifs
dans des feuilles situes au-del de cette valeur.
Tableau5.4: Comparaison des performances d'un index secondaire sur une table
organise en IOT avant et aprs dplacement des cls
Paramtre Avant Aprs
Consistent Gets 3570 4408
CPU 0 2
select count(nom) from clients where pays='Japan';
update clients set NOCLIENT=NOCLIENT+1000000 where pays='Japan';
select count(nom) from clients where pays='Japan';
Il y a une augmentation de 25 % des Consistent Gets lie au fait que les enregis-
trements ne sont plus l o ils devraient tre, daprs les Logical RowID, ce qui
provoque des parcours de lindex intgr de la cl primaire.
valuation de l'espace occup
Concernant le gain despace, si nous testons sur notre base exemple avec la table cmd:
Taille du tas (26Mo) + Index cl primaire (30Mo) = 56Mo.
Taille IOT = 28Mo.
On constate un gain signifcatif. De faon gnrale, la taille de lIOT sera lgre-
ment plus grande que la taille du tas, lcart tant constitu des branches du B*Tree.
Il est noter que plus lindex de cl primaire compte de colonnes et moins les enre-
gistrements en ont, plus le ratio despace conomis est important par rapport une
table organise en tas (ce qui est le cas dans notre exemple).
Par contre, si nous regardons lvolution de la taille de lindex secondaire sur la
colonne Noclient, nous voyons que, sur la table organise en tas, il occupe 18Mo
alors que, sur la table de type IOT, il occupe 25Mo soit presque 40% de plus alors
que la cl primaire est plutt petite puisque cest une valeur numrique.
Overfow segment
Comme nous lavons vu prcdemment, une table de type IOT a pour effet de pnali-
ser les oprations pouvant se faire uniquement sur lindex de la cl primaire, puisque
lindex contient prsent lensemble des champs. Afn de rduire cet impact, il est
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 127
possible de mettre en uvre un segment de dbordement (overfow segment), qui
est, en fait, une table organises en tas contenant une partie des champs.
Cette solution fait chuter les performances quand il faut souvent rcuprer les don-
nes qui sont dans ce segment par exemple, dans le cas dun Full Table Scan qui
aurait besoin des donnes qui sont situes dans le segment de dbordement. Par
contre, dans les autres cas, les performances sont meilleures car la partie index de la
table IOT est moins volumineuse.
La mise en uvre se fait avec les mots cls OVERFLOW et INCLUDING qui prcisent la
dernire colonne tre dans la partie index, les colonnes suivantes seront donc dans
le segment de dbordement (ci-aprs: Jobhistory et Managercomments).
CREATE TABLE IOTEMPOverow (
EMPNO NUMBER ,
ENAME VARCHAR2(10) NOT NULL ,
JOB VARCHAR2(9) ,
JobHistory VARCHAR2(4000),
ManagerComments VARCHAR2(4000),
constraint PK_IOTEMPOverow primary key(empno))
Organization index including JOB overow ;
MS SQL Server
Nous retrouvons sous SQL Server la mme fonctionnalit sous le nom de Clustered Index.
La cration d'un index clustered (un seul possible par table) aura pour effet de transfor-
mer la table d'une organisation en tas en une organisation en index.
Par dfaut, une cl primaire cre un index de type clustered. Donc, si le contraire n'est pas
spcif, toute table qui a une cl primaire est de type Index Organized Table.
Dans l'instruction CREATE TABLE, la clause CONSTRAINT permet de prciser le type d'index:
CONSTRAINT constraint_name
{ { PRIMARY KEY | UNIQUE } [ CLUSTERED | NONCLUSTERED ] }
Les index secondaires sont par dfaut NON CLUSTERED :
CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name
ON <object> ( column [ ASC | DESC ] [ ,...n ] )
Concernant les index secondaires sur table IOT, contrairement ce qui se passe avec
Oracle, l'index ne contient pas de Logical RowID mais seulement la cl de la table. Cela a
pour effet de moins pnaliser les index secondaires sur IOT de SQL Server que sur Oracle
si les enregistrements changent de bloc mais ils seront un peu moins performants si la
table a une croissance respectant l'ordre de la cl. L'index souffre par contre du mme
problme de taille si la cl primaire n'est pas petite, bien que cela soit un peu rduit par
l'absence du Logical RowID.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
128 tude et optimisation desrequtes Axe 2
MySQL
Le moteur InnoDB utilise un stockage de type IOT exclusivement.
Le moteur MyISAM ne propose pas d'option pour implmenter les IOT.
C'est donc le type de la table dans les instructions CREATE TABLE et ALTER TABLE qui d-
cidera du type de l'organisation de la table.
CREATE TABLE tbl_name (create_denition,...)
{ENGINE|TYPE} = {InnoDB| MYISAM}
valuation des performances
Effectuons un premier test sur une requte portant uniquement sur les index:
select count(*) from cmd_lignes
Figure5.15
Trace d'excution
sur une table Heap.
Figure5.16
Trace d'excution
sur une table IOT.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 129
Les requtes portant uniquement sur lindex de cl primaire sont plus rapides sur
des table organises en tas plus B*Tree car lindex B*Tree est plus petit (56Mo)
que la table IOT (75Mo). Sur la table organise en IOT, on constate un Index Fast
Full Scan, ce qui est quivalent un Full Table Scan sur une table organise en tas.
Sur les requtes ncessitant uniquement lutilisation dindex secondaires, lavantage
sera l aussi aux tables organises en tas car, nous lavons vu, les index secondaires
sont plus petits sur les tables organises en tas que sur les tables IOT, mais lcart
sera gnralement moindre quavec lusage de la cl primaire.
Nous allons faire un deuxime test portant sur un parcours dintervalles de la cl
primaire ncessitant daccder des colonnes non indexes. La requte ci-aprs
travaille sur une plage de 5477enregistrements
select sum(montant) from cmd_lignes
where nocmd between 100000 and 102000;
On constate que loptimiseur dcide deffectuer un Range Scan sur lindex de cl
primaire pour rcuprer les enregistrements correspondants par leur RowID afn
deffectuer le calcul de la somme.
Figure5.17
Trace d'excution sur une
table organise en tas.
la Figure 5.18, on voit que le SGBDR scanne uniquement la partie de la table
concerne et rcupre les donnes dans la mme passe. On a un meilleur temps de
rponse et moins de Consistent Gets. Cest le cas de prdilection de lIOT
1
.
1. En fonction du facteur de foisonnement des donnes du test ralis sur la table organise en HEAP, le
gain pourrait tre encore plus important.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
130 tude et optimisation desrequtes Axe 2
Figure5.18
Trace d'excution sur une
table organise en IOT.
Nous allons raliser un troisime test, analogue au prcdent mais portant sur
un intervalle plus important. La requte ci-aprs travaille sur un intervalle de
261205enregistrements, soit 10% de la table.
select sum(montant) from cmd_lignes
where nocmd between 100000 and 200000
Sur la table organise en tas, loptimiseur choisit de faire un Full Table Scan sans
laisser la table en cache (visible car chaque excution contient des Physical Reads)
[voir Figure5.19].
Figure5.19
Requte sur une table
organise en tas.
Sur la table organise en index (IOT), loptimiseur fait un Range Scan en suivant la
cl primaire, ce qui est toujours le cas de prdilection des IOT. De plus, il laisse la
table en cache, probablement cause de son statut dindex (voir Figure5.20).
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 131
Si on augmente encore lintervalle pour couvrir 50% de la table, on constate que
loptimiseur ne choisit plus de faire dIndex Range Scan sur lIOT mais un Index
Fast Full Scan. Cela vient probablement du fait quun Index Range Scan parcourt les
blocs dans lordre de lindex et effectue donc des lectures alatoires alors quun
Index Fast Full Scan privilgie des lectures squentielles en lisant les blocs dans
lordre du segment. Or, selon la performance du disque ou selon que les donnes
soient en cache ou pas, le surcot dune lecture alatoire compare une lecture
squentielle peut se rduire de faon signifcative par rapport aux cots estims qui
sont de 5656 pour la version Full Scan et de 10401 pour la version Range Scan. Si
nous forons un Index Range Scan laide du hint INDEX_RS, nous constatons une
rduction des Consistent Gets de 9109 4535 et une rduction du temps dex-
cution de 1,43 seconde 0,91 seconde, nous avons donc un rsultat diffrent de
lestimation de loptimiseur.
Figure5.20
Requte sur une table
organise en IOT.
Nous pourrions penser que cela est d au fait que les donnes sont dans le cache,
mais si nous excutons linstruction alter system ush buffer_cache; pour vider
le cache et que nous rexcutions les requtes, nous trouverons des quantits de Phy-
sical Reads et de Consistent Gets trs proches. Malgr tout, nous observons la mme
tendance, la version Range Scan sexcute en 3,78secondes et la version Full Scan
en 6,15secondes. Les choses pourraient tre diffrentes suivant la faon dont la table
a t remplie, les performances des disques, etc. Donc, comme toujours, testez!
select /*+index_rs(t)*/ sum(montant) from cmd_lignes_iot t
where nocmd between 100000 and 600000
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
132 tude et optimisation desrequtes Axe 2
5.3.3 Cluster
Le cluster est un objet doptimisation qui existe depuis longtemps dans les bases
Oracle mais qui na jamais connu de franc succs, ce qui, de mon point de vue, est
tout fait justif tant donn les problmes quil pose. Ce chapitre a donc pour
principal objet dexpliquer le fonctionnement des clusters et la raison pour laquelle
ils ne vont probablement pas vous convenir. Je nexclus cependant pas le fait que,
dans quelques cas, ils puissent tre intressants.
Un cluster est un regroupement entre deux tables pour simplifer, on pourrait dire
quun cluster est une jointure forte. Cest un objet qui est orient pour des tables
ayant entre elles une relation matre/dtails. Lide est que le cluster va stocker dans
une mme zone ces deux tables au lieu de les stocker dans deux zones distinctes.
Il pousse mme la chose jusqu stocker les enregistrements matres et les enregis-
trements dtails dans le mme bloc de donnes. Lintrt rside dans le fait que,
lorsque vous faites une jointure entre ces deux tables, en lisant un seul bloc vous
rcuprez les donnes matres et dtails et en plus il ny a pas de choses compliques
faire pour raliser la jointure.
Pour linstant, le cluster a lair formidable, voyons donc o est le problme. Afn de
pouvoir stocker les enregistrements dtails avec lenregistrement matre, le cluster
va rserver un bloc (soit gnralement 8Ko) pour chaque cl, ce qui risque davoir
pour effet de faire exploser lespace ncessaire pour stocker les donnes et ainsi
daugmenter le nombre dE/S, ce qui sera fnalement assez pnalisant.
Par exemple, sur notre base de test, o nous allons nous limiter 100000commandes
au lieu dun million:
Tas et cl primaire de cmd + cmd_lignes = 56Mo + 130Mo = 186Mo pour un
million de commandes soit environ 20Mo pour 100000commandes.
Cluster CLUS_CMD plus les index = 811Mo + 9Mo + 4Mo + 3Mo = 827Mo soit
un peu plus de 40fois plus.
Avec une taille de bloc de 2Ko (la plus petite valeur possible) au lieu 8Ko, lespace
occup ne serait plus que de 200Mo ce qui est encore 10fois plus que sans cluster.
Exemple de cration de tables dans un cluster:
create cluster CLUS_CMD (NoCmd number) size 8k;
Create Index IDX_CLUS_CMD ON CLUSTER CLUS_CMD;
Create Table CMD_CLUS (
NOCMD NUMBER not null,
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 133
NOCLIENT NUMBER,
DATECOMMANDE DATE,
ETATCOMMANDE CHAR(1),
Constraint PK_clus_CMD primary key (NoCmd))
cluster CLUS_CMD(NoCmd);
Create Table CMD_LIGNES_CLUS (
NOCMD NUMBER not null,
NOLIVRE NUMBER not null,
QUANTITE NUMBER,
REMISE NUMBER,
MONTANT NUMBER,
constraint PK_CLUS_CMD_LIGNES primary key (NOCMD, NOLIVRE),
constraint FK_CLUS_CMD_LIGNES_CMD foreign key (NOCMD) references CMD_
CLUS(NOCMD) )
cluster CLUS_CMD(NOCMD);
insert into CMD_CLUS select * from CMD where nocmd <114524;
commit;
insert into CMD_LIGNES_CLUS select * from CMD_LIGNES where nocmd <114524;
commit;
valuation
Nous allons vrifer avec quelques tests si cette mauvaise rputation est mrite ou
pas. Nous allons excuter la requte suivante qui porte sur quelques milliers den-
registrements (10 000 commandes et 25 000 lignes de commandes) et utilise des
donnes de la table matre cmd et de la table dtails cmd_lignes en fltrant par la
cl du cluster, savoir le champ Nocmd (cas dutilisation optimale du cluster). Cet
exemple est un peu compliqu, le champ Montantremisemardi a seulement pour but
dempcher loptimiseur de simplifer la requte afn de forcer la jointure.
select avg(montanttotal) MontantMoyen,avg(NbrItem)NbrItemMoyen,
sum(NbrItem) NbrTotalItem,count(distinct nocmd) NbrCmd,
sum(montanttotal) MontantTotal,sum(MontantRemiseMardi) TotalRemiseMardi
from (
select c.nocmd,c.datecommande,sum(montant) montanttotal,count(*) NbrItem
,sum(case when to_char(c.datecommande,'d')=2 then montant*0.03
else 0 end) MontantRemiseMardi
from cmd_clus c join cmd_lignes_clus cl on c.nocmd=cl.nocmd
where c.nocmd between 70000 and 80000
group by c.nocmd, c.datecommande
);
MONTANTMOYEN NBRITEMMOYEN NBRTOTALITEM NBRCMD MONTANTTOTAL TOTALREMISEMARDI
------------ ------------ ------------ ---------- ------------ ----------------
221,324 2,488 24884 10001 2213465,18 7977,66
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
134 tude et optimisation desrequtes Axe 2
Nous constatons un avantage signifcatif en temps dexcution pour la solution clus-
ter car pour notre test les blocs impliqus restent dans le cache. Si nous vidons
le cache laide de linstruction alter system ush buffer_cache;, la solution
cluster ncessite 10 038 Physical Reads et 11,7 secondes contre 5,7 secondes et
8360Physical Reads. La tendance se confrme de la mme faon, en dfaveur du
cluster, si nous augmentons la taille de lintervalle parcourir qui aura pour effet
daugmenter le nombre de blocs et donc de rduire leur probabilit de prsence en
cache. Le cot estim par loptimiseur de chacune des solutions confrme dailleurs
cette tendance dfavorable pour le cluster.
La solution cluster est donc intressante sil y a assez denregistrements pour
quune jointure soit coteuse, mais pas trop, pour que la taille ne devienne pas
pnalisante. Pour la plupart des autres cas, le cluster sera viter. Cela laisse une
plage dintrt assez rduite. Si votre problmatique sy trouve, alors il peut y avoir
des gains signifcatifs, mais si ce nest pas clairement le cas, je vous conseille de
rester lcart de cet objet qui peut vous faire payer assez cher le fait de lavoir
choisi tort.
Figure5.21
Trace d'excution
sans cluster.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 135
Figure5.22
Trace d'excution
avec cluster.
5.3.4 Partitionnement des donnes
Le partitionnement permet de diviser une grosse table en morceaux physiquement
plus petits (les partitions), tout en gardant la vision logique dune grosse table. Ilsera
possible deffectuer des oprations de maintenance sur les partitions individuelle-
ment, ce qui permettra daugmenter la disponibilit des donnes. Les partitions sont
cres partir des valeurs des colonnes qui seront dfnies comme les cls de par-
titionnement. Il peut y avoir jusqu 16colonnes et elles doivent tre spcifes NOT
NULL. Une table peut tre divise en 64000partitions au plus. Oracle11g Release1
introduit la possibilit de partitionner suivant une colonne calcule en autorisant le
partitionnement sur des colonnes virtuelles.
Le partitionnement nest pas disponible sur toutes les ditions dOracle (idem pour
MySQL et MS SQL Server).
Du point de vue de loptimisation, le principal intrt des partitions est que lorsque
loptimiseur pourra dterminer les partitions ncessaires, les requtes nutiliseront
que celles-ci et ignoreront les autres, ce qui amliorera les performances. Il faut
donc, lorsque vous utilisez des tables partitionnes, essayer le plus possible de mettre
des conditions qui permettent de slectionner les partitions concernes. Lautre int-
rt est de pouvoir spcifer les tablespaces associs chaque partition, et ainsi de
rpartir les donnes sur diffrents volumes afn daugmenter les dbits et de pouvoir
parallliser au mieux. Il sera possible, a posteriori, de fusionner, diviser et dplacer
chacune des partitions.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
136 tude et optimisation desrequtes Axe 2
Le partitionnement occupe, presque lui seul, un livre entier dans la documenta-
tion Oracle. Le but ici nest pas dtre exhaustif, mais de donner quelques cls pour
juger si sa mise en uvre est pertinente pour vous, et si elle lest, de vous donner
les bases.
Mise en uvre
Il est possible de partitionner les tables (HEAP ou IOT) et les index (B*Tree ou
bitmap) et de les combiner de diffrentes faons (voir Figure 5.23):
table et index partitionns suivant le mme dcoupage (relativement frquent);
table partitionne et index non partitionn (relativement frquent);
table non partitionne et index partitionn (plutt rare).
Figure5.23
Combinaisons possibles
entre tables partitionnes
et index partitionns.
Table partitionne
Index partitionn
2007 2008 2009
Table partitionne
Index non partitionn
2007 2008 2009
2007 - 2009
Table non partitionne
Index partitionn
2007 - 2009
2007 2008 2009 2007 2008 2009
Il existe principalement trois types de partitionnement:
Figure5.24
Principaux types de
partitionnement.
Europe
Allemagne, France, Espagne
Amrique
USA, Brsil, Mexique
Afrique
Sngal, Cameroun, Bnin
2005 2007
2008
2009
2010

Partition 1
Partitionnement
par liste
Partitionnement
par intervalle
Partitionnement
par hachage
Autres
Partition 2
Partition 3
Partition N
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 137
Partitionnement par liste
Il permet de dfnir pour chaque partition la liste des valeurs qui la constituent plus
la valeur DEFAULT qui reprsente toutes les autres valeurs possibles. Ci-aprs un
exemple du partitionnement de la table clients par la colonne Pays.
create table CLIENTS_PART (
NOCLIENT NUMBER not null,
NOM VARCHAR2(50),
PRENOM VARCHAR2(50),
ADRESSE1 VARCHAR2(100),
ADRESSE2 VARCHAR2(100),
CODEPOSTAL VARCHAR2(10),
VILLE VARCHAR2(50),
PAYS VARCHAR2(50),
TEL VARCHAR2(20),
EMAIL VARCHAR2(50),
constraint PK_CLIENTS_PART primary key (NOCLIENT)
)
PARTITION BY LIST(PAYS)
(
PARTITION Clients_Amerique VALUES('USA','Brsil','Mexique')
tablespace TableSpace1,
PARTITION Clients_Europe VALUES ('Allemagne','France','Espagne')
tablespace TableSpace2,
PARTITION Clients_Afrique VALUES('Sngal','Cameroun','Bnin')
tablespace TableSpace3,
PARTITION Clients_Autres VALUES(DEFAULT) tablespace TableSpace2
);
Partitionnement par intervalle
Il permet de dfnir pour chaque partition lintervalle de valeurs qui la constituent en
spcifant la borne suprieure. Si une valeur est suprieure la plus grande borne,
lopration choue. Pour tre sr de nexclure aucune valeur, il sufft de spcifer la
valeur MAXVALUE qui reprsente la plus grande valeur possible.
create table CMD_PART(
NOCMD NUMBER not null,
NOCLIENT NUMBER,
DATECOMMANDE DATE,
ETATCOMMANDE CHAR(1),
constraint PK_CMD_PART primary key (NOCMD)
)
PARTITION BY RANGE(DATECOMMANDE)
(
PARTITION CMD_2005_2007 VALUES LESS THAN(TO_DATE('01/01/2008','DD/MM/YYYY'))
TABLESPACE TableSpace1,
PARTITION CMD_2008 VALUES LESS THAN(TO_DATE('01/01/2009','DD/MM/YYYY'))
TABLESPACE TableSpace2,
PARTITION CMD_2009_MAX VALUES LESS THAN(MAXVALUE) TABLESPACE TableSpace3
);
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
138 tude et optimisation desrequtes Axe 2
Oracle 11g introduit une variante qui se nomme, en anglais, interval partitioning.
Elle permet de crer automatiquement les partitions au-del de la dernire limite
dfnie, suivant une frquence tablie sur un champ numrique ou date.
create table CMD_PART(
NOCMD NUMBER not null,
NOCLIENT NUMBER,
DATECOMMANDE DATE,
ETATCOMMANDE CHAR(1),
constraint PK_CMD_PART primary key (NOCMD)
)
PARTITION BY RANGE(DATECOMMANDE)
INTERVAL (NUMTOYMINTERVAL(1,'YEAR'))
(
PARTITION CMD_2005_2007 VALUES LESS THAN(TO_DATE('01/01/2008','DD/MM/YYYY'))
TABLESPACE TableSpace1,
PARTITION CMD_2008 VALUES LESS THAN(TO_DATE('01/01/2009','DD/MM/YYYY'))
TABLESPACE TableSpace2,
PARTITION CMD_2009 VALUES LESS THAN(TO_DATE('01/01/2010','DD/MM/YYYY'))
TABLESPACE TableSpace3
);
Partitionnement par hachage
Dans ce type de partitionnement, on dfnit seulement la liste des partitions et la
colonne qui sert de paramtre pour calculer la cl de hachage. Cette solution est la
plus simple mettre en uvre, mais probablement la moins pratique pour dterminer
la manire doptimiser lusage des partitions.
create table CMD_PART_HASH(
NOCMD NUMBER not null,
NOCLIENT NUMBER,
DATECOMMANDE DATE,
ETATCOMMANDE CHAR(1),
constraint PK_CMD_PART_HASH primary key (NOCMD)
)
PARTITION BY HASH(NOCMD)
PARTITIONS 4
STORE IN (Tablespace1, Tablespace2, Tablespace3, Tablespace4);
Partitionnement systme
Introduit en version 11g, il permet de ne donner aucune rgle de rpartition des
donnes entre les partitions la cration de la table mais de grer cette rpartition
dans les instructions INSERT laide du paramtre PARTITION. De la mme faon, il
sera possible de spcifer au niveau des instructions UPDATE, DELETE et SELECT sur
quelle partition porte la requte. La syntaxe dans linstruction CREATE TABLE est
la suivante:
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 139
PARTITION BY SYSTEM (
PARTITION Partition1,
PARTITION Partition2 );
Les requtes dinsertion sur ces tables doivent spcifer la partition utilise laide
du mot cl PARTITION.
insert into TablePartitionnee partition (Partition1) values (. . .);
Pour les requtes UPDATE, DELETE et SELECT, cette directive est optionnelle. Son
absence entrane un parcours de toutes les partitions. Il peut y avoir incohrence
entre la partition dsigne et les autres prdicats, puisque ce point relve de la res-
ponsabilit du dveloppeur.
delete TablePartitionnee partition (Partition1) where . . .;
select * from TablePartitionnee partition (Partition1) where . . .;
Partitionnement combin
On peut combiner deux types de partitionnement afn de faire un partitionnement
composite. Cela signife que vous pourrez spcifer deux axes de partitionnement.
Vous pouvez faire un sous-partitionnement rgulier, cest--dire dcouper toutes les
partitions en sous-partitions identiques laide de SUBPARTITION TEMPLATE, ou un
sous-partitionnement libre, qui sera propre chaque partition mme si le champ per-
mettant le sous-partitionnement est commun toutes les sous-partitions. Lexemple
suivant illustre les deux syntaxes possibles.
Jusqu la version10g, les seules combinaisons possibles taient partition par inter-
valle et sous-partition par Hash ou partition par intervalle et sous-partition par liste.
La version 11g a introduit les possibilits suivantes : Intervalle/Intervalle, Liste/
Intervalle, Liste/Hash, Liste/Liste.
Figure5.25
Exemple de
partitionnement
combin.
Europe
Allemagne
France
Espagne
Sous-partition
Partitionnement
par Pays
P
a
r
t
i
t
i
o
n
n
e
m
e
n
t
p
a
r

N


c
l
i
e
n
t
Sous-partition
Sous-partition
Sous-partition
Sous-partition
Sous-partition
Sous-partition
Sous-partition
Table CLIENTS
avec
partitionnement
combin
Anciens Clients
Noclient < 30 000
Nouveaux Clients
Noclient 30 000
Amrique
USA
Brsil
Mexique
Afrique
Sngal
Cameroun
Bnin
Asie
Chine
Japon
Indonsie
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
140 tude et optimisation desrequtes Axe 2
Exemple de cration d'une table avec des sous-partitions rgulires
create table CLIENTS_PART(
NOCLIENT NUMBER not null,
NOM VARCHAR2(50),
PRENOM VARCHAR2(50),
ADRESSE1 VARCHAR2(100),
ADRESSE2 VARCHAR2(100),
CODEPOSTAL VARCHAR2(10),
VILLE VARCHAR2(50),
PAYS VARCHAR2(50),
TEL VARCHAR2(20),
EMAIL VARCHAR2(50),
constraint PK_CLIENTS_PART primary key (NOCLIENT)
)
PARTITION BY LIST(PAYS)
SUBPARTITION BY RANGE (NOCLIENT)
SUBPARTITION TEMPLATE(
SUBPARTITION Anciens VALUES LESS THAN (30000) TABLESPACE TableSpace1,
SUBPARTITION Recents VALUES LESS THAN (MAXVALUE) TABLESPACE TableSpace2)
(
PARTITION Clients_Amerique VALUES('USA', 'Canada','Brazil'),
PARTITION Clients_Europe VALUES ('Germany', 'United Kingdom',
'France','Italy'),
PARTITION Clients_Asie VALUES('Japan', 'China','India'),
PARTITION Clients_Autres VALUES(DEFAULT)
);
Exemple de cration d'une table avec des sous-partitions libres
create table CLIENTS_PART(
NOCLIENT NUMBER not null,
NOM VARCHAR2(50),
PRENOM VARCHAR2(50),
ADRESSE1 VARCHAR2(100),
ADRESSE2 VARCHAR2(100),
CODEPOSTAL VARCHAR2(10),
VILLE VARCHAR2(50),
PAYS VARCHAR2(50),
TEL VARCHAR2(20),
EMAIL VARCHAR2(50),
constraint PK_CLIENTS_PART primary key (NOCLIENT)
)
PARTITION BY LIST(PAYS)
SUBPARTITION BY RANGE (NOCLIENT)
(
PARTITION Clients_Amerique VALUES('USA', 'Canada','Brazil')
(SUBPARTITION Clients_AM_Anciens VALUES LESS THAN (30000)
TABLESPACE Tablespace1,
SUBPARTITION Clients_AM_Recents VALUES LESS THAN (MAXVALUE)
TABLESPACE Tablespace2),
PARTITION Clients_Europe VALUES ('Germany', 'UK', 'France','Italy')
(SUBPARTITION Clients_EU_Anciens VALUES LESS THAN (30000)
TABLESPACE Tablespace3,
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 141
SUBPARTITION Clients_EU_Recents VALUES LESS THAN (MAXVALUE)
TABLESPACE Tablespace4),
PARTITION Clients_Asie VALUES('Japan', 'China','India')
(SUBPARTITION Clients_AS_Anciens VALUES LESS THAN (30000)
TABLESPACE Tablespace5,
SUBPARTITION Clients_AS_Recents VALUES LESS THAN (MAXVALUE)
TABLESPACE Tablespace6),
PARTITION Clients_Autres VALUES(DEFAULT)
(SUBPARTITION Clients_AU_Anciens VALUES LESS THAN (30000)
TABLESPACE Tablespace7,
SUBPARTITION Clients_AU_Recents VALUES LESS THAN (MAXVALUE)
TABLESPACE Tablespace8)
);
Partitionnement par rfrence
Oracle 11g Release1 a introduit une nouvelle mthode assez intressante. Elle per-
met de partitionner une table en fonction des valeurs contenues dans une autre table
et ayant une relation de rfrence au moyen dune cl trangre (Foreign Key) avec
elle. Ce type de partitionnement a t introduit pour grer des relations de type
matre/dtails. Ci-aprs, un exemple entre la table des commandes et la table des
lignes de commandes est propos:
create table CMD_LIGNES_PART(
NOCMD NUMBER not null,
NOLIVRE NUMBER not null,
QUANTITE NUMBER,
REMISE NUMBER,
MONTANT NUMBER,
constraint PK_CMD_LIGNES_PART primary key (NOCMD, NOLIVRE),
constraint FK_CMD_LIGNES_CMD_PART Foreign key (NOCMD) References CMD_
PART(NOCMD)
)
PARTITION BY REFERENCE (FK_CMD_LIGNES_CMD_PART);
Partitionnement et index
Il existe trois types dindex travaillant avec les partitions:
Les index normaux, qui permettent dindexer des colonnes de faon indpen-
dante des partitions de la table.
Les index locaux prfxs, qui sont calqus sur les partitions et qui reprennent en
premires colonnes les colonnes de la cl de partitionnement.
Les index locaux non prfxs, qui sont calqus sur les partitions et qui ne repren-
nent pas les colonnes de la cl de partitionnement. Ces index-l ne peuvent pas
tre de type unique.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
142 tude et optimisation desrequtes Axe 2
Les index normaux nont pas de spcifcit de syntaxe, seuls les index locaux int-
grent le mot cl LOCAL. Un index local sera dit "prfx" si les premires colonnes
sont celles de la cl de partitionnement. Voici un exemple dindex local prfx:
create index IS_CLIENTS_PART_PAYSVILLE on CLIENTS_PART(pays,ville) local;
Les index locaux non prfxs prennent moins de place car ils ont lavantage de ne
pas rpter la cl de partitionnement, ce qui est intressant pour des partitions mono-
valeurs. Sur les index locaux non prfxs, il faut parfois aider loptimiseur avec un
hint pour quil utilise lindex.
MS SQL Server
La gestion des partitions est propose depuis SQL Server 2005, seul le partitionnement par
intervalle est disponible. Il faut d'abord crer une fonction de partitionnement puis crer
le schma de partitionnement et enfn assigner le schma de partitionnement la table.
CREATE PARTITION FUNCTION myRangePF1 (int)
AS RANGE LEFT FOR VALUES (1, 100, 1000);
CREATE PARTITION SCHEME myRangePS1
AS PARTITION myRangePF1
TO (test1fg, test2fg, test3fg, test4fg);
CREATE TABLE (. . . .) on myRangePS1(id);
MySQL
MySQL propose depuis la version5.1 la gestion des partitionnements Hash, List et Range
mais pas le partitionnement composite ou par rfrence.
valuation
Nous allons valuer le partitionnement en utilisant la table cmd dun million den-
registrements partitionne par intervalles sur la date de commande, comme montr
prcdemment. La requte sera la suivante:
select count(*) from cmd
where datecommande >=to_date('08/2008','MM/YYYY')
and datecommande <to_date('09/2008','MM/YYYY')
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 143
Figure5.26
Trace d'excution
sur table normale.
On constate ici que toute la table est parcourue.
Figure5.27
Trace d'excution
sur la table
partitionne.
On constate ici que seule la partition 2 est parcourue, do une chute des Consistent
Gets et du temps dexcution.
Partitionnement conomique
Comme nous lavons dit, le partitionnement nest pas prsent dans toutes les di-
tions des produits. Pour avoir cette option, il faut souvent acqurir les versions haut
de gamme et ce nest pas forcment compatible avec votre budget. Je vais vous
prsenter une solution alternative ci-aprs, oriente base dcisionnelle. On peut cer-
tainement ladapter un usage OLTP, laide dun trigger INSTEAD OF, et simuler
compltement le partitionnement, mais je ne vous le conseille pas.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
144 tude et optimisation desrequtes Axe 2
Une solution plus conomique consiste crer autant de tables quon aurait cr de
partitions et adapter les requtes cette nouvelle organisation des donnes. Cela
demandera sans doute pas mal de travail.
Une faon de rduire ce travail est dagrger les tables dans une vue qui se nommera
comme se nommait la table avant que vous ne la coupiez en morceaux. De cette
faon, les requtes marcheront toujours. Cependant, si on ne fait rien de plus, le
rsultat sera peu intressant, si ce nest de pouvoir profter dun peu de paralllisme.
En fait, pour que cela prsente un intrt, nous allons appliquer des contraintes de
type CHECK dfnissant des intervalles sur les colonnes qui servent de pseudo-cls de
partitionnement. Nous allons donc crerles objets suivants :
create table CMD_2005_2007 (
NOCMD NUMBER not null,
NOCLIENT NUMBER,
DATECOMMANDE DATE constraint CMD_2005_2007_CKPART
check (DateCommande<TO_DATE('01/01/2008','DD/MM/YYYY')),
ETATCOMMANDE CHAR(1),
constraint PK_CMD_2005_2007 primary key (NOCMD)
);
create table CMD_2008 (
NOCMD NUMBER not null,
NOCLIENT NUMBER,
DATECOMMANDE DATE constraint CMD_2008_CKPART
check (DateCommande>=TO_DATE('01/01/2008','DD/MM/YYYY')
and DateCommande<TO_DATE('01/01/2009','DD/MM/YYYY')),
ETATCOMMANDE CHAR(1),
constraint PK_CMD_2008 primary key (NOCMD)
);
create table CMD_2009_MAX (
NOCMD NUMBER not null,
NOCLIENT NUMBER,
DATECOMMANDE DATE constraint CMD_2009_MAX_CKPART
check (DateCommande>=TO_DATE('01/01/2009','DD/MM/YYYY')),
ETATCOMMANDE CHAR(1),
constraint PK_CMD_2009_MAX primary key (NOCMD)
);
create view CMD_PART as
select * from CMD_2005_2007
union all
select * from CMD_2008
union all
select * from CMD_2009_MAX;
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 145
Puis excuter la requte suivante :
select count(*) from cmd
where datecommande >=to_date('08/2008','MM/YYYY')
and datecommande <to_date('09/2008','MM/YYYY')
Figure5.28
Trace d'excution
d'une requte
sur une vue
Union All
de table avec des
contraintes.
Des cots sont assigns linterrogation des tables cmd_2005_2007 et cmd_2009_
max, mais nous voyons dans la colonne Last_Output_Rows quaucune ligne nest
rcupre. Cela vient de lajout dans le plan dexcution de prdicats faux NULL IS
NOT NULL qui ont pour effet de "couper" ces branches dexcution. Nous retrouvons
donc en interrogation les mmes performances quavec le partitionnement classique,
linsertion des donnes, elle, nest pas gre.
MS SQL Server
Il est possible d'utiliser la mme astuce sous SQL Server, c'tait d'ailleurs la solution recom-
mande avant la version2005, qui intgre le partitionnement.
MySQL
Pour cette opration, MySQL propose le moteur MERGE sur les tables MyISAM pour ce
genre d'astuce mais l'absence de contrainte CHECK empchera d'utiliser la mme astuce.
Le moteur MERGE permet de spcifer la table dans laquelle il faut faire les insertions.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
146 tude et optimisation desrequtes Axe 2
5.3.5 Les vues matrialises
Les vues matrialises (Materialized Views) sont des tables qui contiennent des don-
nes agrges ou jointes issues dautres tables. Elles sont dfnies par des requtes,
comme les vues, mais stockent les donnes comme les tables.
Le mcanisme de journalisation MATERIALIZED VIEW LOG permet de capturer les
changements sur les donnes sources afn de faire des rafrachissements incrmentaux
(Fast Refresh).
Les vues matrialises peuvent tre rafrachies en temps rel, lors des COMMIT (obli-
gatoirement FAST REFRESH), ou manuellement, la demande. Nous tudions cet objet
en tant quobjet doptimisation, nous nous focaliserons donc sur le mode REFRESH
ON COMMIT. Cependant, dans le cas de mises jour des tables par lot (batch), un
rafrachissement manuel pourrait tre plus adapt.
Mesurez bien les consquences en espace disque, en ressources CPU et en temps de
rponse sur les tables sources lors de lutilisation de REFRESH ON COMMIT. En effet,
chaque transaction a pour effet dactualiser de faon synchrone les donnes impactes
des vues matrialises.
Lutilisation des Materialized View et du Query Rewriting (voir ci-aprs) ncessite
davoir les privilges suivants (mme si on est DBA):
GRANT GLOBAL QUERY REWRITE TO scott;
GRANT CREATE MATERIALIZED VIEW to scott;
Un exemple de mise en uvre dune vue matrialise maintenue de faon incrmen-
tale sur COMMIT est le suivant: nous commenons par crer les MATERIALIZED VIEW
LOG. Ils permettent de capturer tous les changements sur les donnes sources afn de
les rpercuter de faon incrmentale sur la vue matrialise sans avoir la recalcu-
ler entirement (il faut ny mettre que les champs impliqus dans la vue). Ensuite,
nous crons la vue matrialise elle-mme. REFRESH FAST ON COMMIT permet de
prciser quelle sera maintenue de faon incrmentale chaque COMMIT et ENABLE
QUERY REWRITE de signaler que cette vue peut tre utilise dans le cadre du Query
Rewriting. Puisque notre requte effectue des agrgats de donnes, il y a quelques
contraintes, entre autres, il doit imprativement y avoir une colonne count(*) et
count(...) de chaque colonne concerne par une somme ou moyenne.
-- Cration de la journalisation sur les donnes sources
CREATE MATERIALIZED VIEW LOG ON cmd WITH SEQUENCE
,ROWID(nocmd,noclient,datecommande,etatcommande) INCLUDING NEW VALUES;
CREATE MATERIALIZED VIEW LOG ON cmd_lignes WITH SEQUENCE
,ROWID (NoCmd,Montant) INCLUDING NEW VALUES;
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 147
-- Cration de la vue
CREATE MATERIALIZED VIEW MV_CMD
PCTFREE 0
BUILD IMMEDIATE
REFRESH FAST on commit
with rowid
ENABLE QUERY REWRITE
AS select c.nocmd,c.noclient,c.datecommande,c.etatcommande
,sum(cl.montant) MontantCMD, COUNT(*) NbrItem
,count(Montant) NbrMontant
from cmd c join cmd_lignes cl on c.nocmd=cl.nocmd
group by c.nocmd,c.noclient,c.datecommande,c.etatcommande;
-- Cration d'un index sur la vue
create index is_MV_CMD_NoCmd on MV_CMD (NoCMD);
Une fois la vue matrialise cre, nous pouvons lutiliser plutt que les donnes
sources dans nos requtes. Elle sera mise jour automatiquement chaque COMMIT.
Query Rewriting
Ce processus permet loptimiseur de rcrire de faon transparente des requtes
crites sur les donnes sources dune vue matrialise pour utiliser celle-ci la
place, si cela est plus performant. Si la vue matrialise est maintenue manuelle-
ment, toute modifcation sur une des tables sources invalidera le fonctionnement du
Query Rewriting jusqu ce que la vue matrialise soit rafrachie. Par exemple, la
requte suivante:
select sum(cl.montant)
from cmd c join cmd_lignes cl on c.nocmd=cl.nocmd
where c.NoCmd=18331
sera transforme de faon transparente par le Query Rewriting en:
select MontantCMD from MV_CMD where NoCmd=18331 ;
Comme on peut le voir sur ce plan dexcution, loptimiseur a dcid dutiliser les
donnes agrges dans la vue matrialise pour rpondre la requte qui portait
sur les donnes non agrges. On constate quil ny a plus daccs aux tables men-
tionnes dans la requte, lutilisation de la vue matrialise vite donc de faire la
jointure. Si nous avions demand AVG(Montant), la requte aurait aussi t rcrite
car avg(Montant)= sum(Montant)/ count(Montant) qui utilise deux oprandes
prsents dans la vue matrialise.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
148 tude et optimisation desrequtes Axe 2
Figure5.29
Trace d'excution d'une
requte rcrite par
l'optimiseur.
MS SQL Server
Sous SQL Server, la mme fonctionnalit existe sous le nom de "vue indexe". Les noms
des tables doivent imprativement tre prfxs par le schma qui les contient. Les agr-
gats ne doivent pas manipuler de valeurs nulles (d'o l'utilisation de ISNULL) et doivent
contenir un COUNT_BIG(*). Il faut ensuite indexer cette vue pour la matrialiser.
create view MV_CMD WITH SCHEMABINDING AS
select c.nocmd,c.noclient,c.datecommande,c.etatcommande
,sum(isnull(cl.montant,0)) MontantCMD
,COUNT_BIG(*) NbrItem
from dbo.cmd c join dbo.cmd_lignes cl on c.nocmd=cl.nocmd
group by c.nocmd,c.noclient,c.datecommande,c.etatcommande;
CREATE UNIQUE CLUSTERED INDEX IDX_MV_CMD ON dbo.MV_CMD(NoCmd);
MySQL
Il n'y a pas, sous MySQL, de fonctionnalit quivalente.
5.3.6 Reconstruction des index et des tables
Les mouvements lis au LMD (insert, update, delete) peuvent entraner une frag-
mentation des segments et ainsi aboutir des tables et des index "gruyres". Ce
phnomne aura pour effet daugmenter inutilement le nombre de blocs manipuler
et donc de rduire les performances. Pour les tables qui subissent beaucoup dajouts
et de suppressions, ces oprations peuvent tre intressantes. Pour les autres, elles
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 149
seront gnralement inutiles car les mcanismes de base de rutilisation des espaces
librs seront suffsamment effcaces.
Les instructions de reconstruction permettent, avec certaines options (MOVE et
REBUILD), de spcifer de nouvelles clauses de stockage et mme de changer de
tablespace. Les reconstructions sont utiles aussi pour supprimer les effets des
migrations de lignes (voir Chapitre 1, section 1.2.5, "Row Migration et Row
Chaining").
Pour rorganiser les tables organises en tas, il faut avant tout autoriser les mouve-
ments de lignes:
Alter table Clients Enable Row Movement;
Le dplacement dune table permet de la compacter en faisant une copie. Cette
option est assez effcace mais, pendant lopration de copie, lespace requis est le
double de lespace initial. Cette option permet aussi de spcifer de nouveaux para-
mtres de stockage:
Alter table <NomTable> move;
ATTENTION
Cette instruction a pour effet particulirement signifcatif d'invalider tous les index. Il fau-
dra donc les reconstruire, ce qui peut avoir un cot certain. Le script PL/SQL ci-aprs permet
de reconstruire tous les index invalids:
begin
for r in (SELECT 'alter index '||index_name||' rebuild' cmd
from user_indexes where status='UNUSABLE')
loop
execute immediate r.cmd;
end loop;
end;
Une variante est linstruction SHRINK TABLE qui ne marche que sur les segments
situs dans des tablespaces en mode ASM (Automatic Storage Management) qui
nutilisent pas dindex sur fonction:
Alter table clients shrink space;

Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
150 tude et optimisation desrequtes Axe 2
Pour rorganiser les index, deux options sont disponibles:
REBUILD. Cest la reconstruction, opration effcace mais particulirement
coteuse:
Alter index <NomIndex> rebuild ;
COALESCE. Solution plus lgre, elle fusionne les feuilles dindex conscutives,
qui ont plus de 25% despace libre sans librer lespace des feuilles:
Alter index <NomIndex> coalesce ;
Impact sur la volumtrie et les performances
Afn dvaluer limpact des reconstructions, nous allons effectuer quelques oprations
sur la table clients.
Taille initiale. Table: 5120Ko; index cl primaire: 768 Ko; IS_CLIENTS_PAYS:
1024Ko.
1. Nous dupliquons la table sur elle-mme afn de doubler sa taille.
Taille aprs doublement. Table: 10240Ko; index cl primaire: 2048Ko; IS_
CLIENTS_PAYS: 3072Ko.
2. Nous effaons la moiti des enregistrements.
Taille aprs effacement. Table: 10240Ko; index cl primaire: 2048Ko; IS_
CLIENTS_PAYS: 3072Ko.
Comme on le voit, lespace nest pas libr.
3. Nous effectuons un SHRINK sur la table et un REBUILD des index:
alter table CLIENTS shrink space;
alter index PK_CLIENTS rebuild;
alter index IS_CLIENTS_PAYS rebuild;
Taille aprs SHRINK et REBUILD. Table: 5120Ko; index cl primaire: 832Ko;
IS_CLIENTS_PAYS: 1024Ko.
Nous revenons la taille initiale.
En termes despace occup, limpact est signifcatif. Ces oprations de maintenance
peuvent tre importantes si des oprations volumineuses ont eu lieu sur les tables (ce
qui narrive normalement pas tous les jours dans la plupart des applications).
Voyons prsent limpact de la dfragmentation sur les performances.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 5 Techniques doptimisation standard au niveau base de donnes 151
Table full scan.
Avant: Consistent Gets: 26302; timing: 2,05s
Aprs: Consistent Gets: 8608; timing: 1,33s
Index full scan.
Avant: Consistent Gets: 532; timing: 0,033s
Aprs: Consistent Gets: 227; timing: 0,032s
Index direct par recherche d'une valeur unique.
Avant: Consistent Gets: 2; timing: 0,005s
Aprs: Consistent Gets: 2; timing: 0,002s
Limpact le plus signifcatif est sur le Table Full Scan qui lit tous les blocs de la
table. On remarque que lindex, lui, saccommode plutt bien de leffet gruyre.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
6
Techniques doptimisation
standard des requtes
Loptimisation du SQL est un point trs dlicat car elle ncessite de pouvoir modifer
lapplicatif en veillant ne pas introduire de bogues.
6.1 Rcriture des requtes
Lutilisation dobjets doptimisation est un lment qui, de manire gnrale, am-
liore les performances trs signifcativement. Cependant, la faon dcrire votre
requte peut, elle aussi, dans certains cas, avoir un impact trs signifcatif.
Ltape de transformation de requte (voir ci-aprs) est de plus en plus performante
sur Oracle et SQL Server. Elle donne de trs bons rsultats, ce qui rend inutiles
certaines recommandations dans le cas gnral. Cependant, sur MySQL ou sur des
requtes compliques, o on peut considrer que le SGBDR narriverait pas faire
certaines transformations tout seul, lutilisation des critures les plus performantes
permettra damliorer les rsultats.
Nous allons faire quelques comparaisons dcritures qui intgreront parfois un hint
(voir Chapitre7, section7.1, "Utilisation des hints sous Oracle") afn dempcher
certaines transformations.
De faon gnrale, il faut privilgier les jointures. Le principe du modle relationnel
tant que, lors de linterrogation, des jointures seront faites, on peut supposer que les
diteurs de SGBDR ont concentr leurs efforts l-dessus. Cependant, sous MySQL
avec le moteur MyISAM, les sous-requtes sont souvent plus performantes.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
154 tude et optimisation desrequtes Axe 2
6.1.1 Transformation de requtes
Ltape de transformation de requtes (Query Transformation) est partie intgrante du
processus de traitement des requtes. Cest une des fonctions de loptimiseur CBO.
Cette tape consiste transformer la requte soumise en une requte quivalente
afn de la rendre plus performante. Cela va, au-del, de choisir le meilleur chemin
dexcution. La transformation de requtes peut, par exemple, dcider de transfor-
mer une sous-requte en jointure. Vous pouvez infuer sur cette tape au moyen des
hints, mais cest rarement ncessaire.
Les principales transformations effectues par le CBO sont:
Subquery unesting. Cette transformation consiste transformer des sous-
requtes en jointures.
Suppression dlments inutiles (certaines jointures, des colonnes slectionnes
dans les sous-requtes).
Predicate push. Cette transformation consiste dupliquer certains prdicats
dans les sous-vues et les sous-requtes.
View merging. Intgre lexcution des vues la requte principale.
Query Rewriting. Utilisation des vues matrialises (voir Chapitre5, section5.3.5,
"Les vues matrialises").
Or Expansion. Transforme des conditions OR en plusieurs requtes fusionnes
par une sorte d"Union ALL".
Il ny a rien de particulier faire pour bnfcier du Query Rewriting. Connatre
lexistence de ce mcanisme vous aidera comprendre pourquoi il arrive parfois
quun plan dexcution ne ressemble vraiment pas votre requte. Cette fonction est
plus volue sous Oracle et SQL Server que sous MySQL.
INFO
Au cours de ce chapitre, nous prsentons des variations de notation qui peuvent avoir un
effet sur les performances. L'optimiseur tant assez performant, il transforme automatique-
ment les requtes soumises en la version la plus performante. Nous recourrons des hints
pour empcher ces transformations afn de comparer les notations. L'utilisation de hint n'est
nullement une recommandation, nous le mentionnons titre indicatif de faon que, si vous
excutez ces requtes, vous puissiez reproduire les mmes rsultats que ceux prsents ici.
Comme cela sera expliqu au Chapitre7, section7.1, "Utilisation des hints sous Oracle", il
faut les utiliser en dernier recours et seulement en toute connaissance de cause.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 6 Techniques doptimisation standard des requtes 155
6.1.2 IN versus jointure
Selon que lcriture dune requte se fasse avec une sous-requte et loprateur IN
ou avec une jointure, limpact sera diffrent. Pour forcer le parcours des tables,
et non seulement celui des index, nous utilisons dans la requte des champs non
indexs (Quantit et Editeur).
Listing6.1: Requte utilisant une jointure
select sum(CL.quantite) from cmd_lignes CL,livres L
where CL.nolivre = L.nolivre and L.editeur='Pearson'
Listing6.2: Requte utilisant une sous-requte
select sum(quantite) from cmd_lignes
where nolivre in (select nolivre from livres where editeur='Pearson')
Nous allons tester ces requtes avec et sans index sur la colonne Nolivre de la table
cmd_lignes.
create index IS_cmd_lignes on cmd_lignes(nolivre);
Sans index Avec index
MyISAM Jointure Sous-requte Jointure Sous-requte
Temps 12,89s 13,53s 0,01s 13,53s
Key_read_requests 5242448 5243442 158 5243442
InnoDB Jointure Sous-requte
Temps 3,48s 13,51s
Reads 3700 2606480
InnoDB crant automatiquement un index dans la table flle de la Foreign Key, il y
a forcement un index sur la colonne Nolivre de la table cmd_lignes. La cration de
lindex est donc sans effets.
Sans index Avec index
Oracle Jointure Sous-requte Jointure Sous-requte
Temps 6,15s 8,75s 0,01s 0,60s
Consistent Gets 8336 4891735 807 12175
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
156 tude et optimisation desrequtes Axe 2
Pour viter la transformation de la version utilisant une sous-requte en version
jointure par le mcanisme de transformation de requte, nous devons utiliser le hint
/*+no_unnest*/ et pour forcer lusage de lindex, le hint /*+ index (CL IS_cmd_
lignes)*/. Si nous ne mettons aucun hint, loptimiseur choisit systmatiquement de
faire une jointure sans utiliser lindex.
Sans index Avec index
MS SQL Server Jointure Sous-requte
Temps 0,625s 0,046s
Estimated Cost 35,27 60,44
Afn de comparer les rsultats entre les bases, nous dsactivons le paralllisme sous
SQL Server au moyen du code option (MAXDOP 1).
Nous navons pas trouv de combinaisons de hints permettant de forcer lutilisa-
tion dune sous-requte tant quil ny a pas dindex. Une fois lindex plac, nous
avons d contraindre son utilisation avec le hint WITH (INDEX(IS_CMD_LIGNES)). En
revanche, nous navons pas russi forcer une jointure pertinente utilisant cet index.
Conclusion : Oracle et SQL Server, grce leur capacit de transformation de
requte volue, excutent les requtes de la mme faon quelle que soit la notation
employe, si aucun hint nest utilis.
Lorsque la transformation nest pas effectue, on constate que la solution base de
jointure est gnralement plus performante.
Au cas o le SGBDR narriverait pas faire la transformation, il est prfrable de
prendre lhabitude dcrire des jointures plutt que des sous-requtes.
6.1.3 Sous-requtes versus anti-jointures
Une anti-jointure est une jointure ouverte pour laquelle vous ne slectionnez que les
valeurs non jointes.
Les requtes ci-dessous, permettent de slectionner les livres qui nont jamais t
commands.
Listing6.3: Version Exists
select * from livres L
where not exists (select 1 from cmd_lignes CL where CL.NOLIVRE=L.NOLIVRE)
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 6 Techniques doptimisation standard des requtes 157
Listing6.4: Version anti-jointure
select L.* from livres L
left outer join cmd_lignes CL on CL.NOLIVRE=L.NOLIVRE
where cl.nolivre is null
Nous allons tester ces requtes avec et sans index sur la colonne Nolivre de la table
cmd_lignes.
create index IS_cmd_lignes on cmd_lignes(nolivre);
Sans index Avec index
MyISAM Anti-jointure Sous-requte Anti-jointure Sous-requte
Temps 10,11s 10,11s 0,02s 0,02s
Key_read_requests 29850364 29850364 2974 2974
L'anti-jointure est transforme en sous-requte.
InnoDB Anti-jointure Sous-requte
Temps 24,31s 25,34s
Reads 2976 5948
InnoDB crant automatiquement un index dans la table flle de la Foreign Key, il y
a forcment un index sur la colonne Nolivre de la table cmd_lignes. La cration de
lindex est donc sans effets.
Sans index Avec index
Oracle Anti-jointure Sous-requte Anti-jointure Sous-requte
Temps 0,340s 2,282s 0,375s 0,031s
Consistent Gets 6976 113419 5522 8909
Nous utilisons le hint /*+NO_QUERY_TRANSFORMATION*/ pour empcher la transfor-
mation de la sous-requte en anti-jointure.
Sans index Avec index
MS SQL Server Anti-jointure Anti-jointure
Temps 2,437s 0,079s
Estimated Cost 47,49 0,54
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
158 tude et optimisation desrequtes Axe 2
Quelle que soit la notation utilise, la requte est transforme en anti-jointure.
Les rsultats sont mitigs sous Oracle. Malheureusement, ltape de transformation
de requte nopte pas toujours pour la meilleure option. Loptimiseur choisit syst-
matiquement lanti-jointure qui est, en effet, gnralement la meilleure option. Ici, la
table livre est bien plus petite que la table cmd_lignes, dans ce cas, si un index est
prsent sur la table flle de la Nested Loop, la solution utilisant une sous-requte est
la meilleure. Il faut donc utiliser un hint pour forcer ce choix. Sur les autres SGBDR,
ltape de transformation ne laisse pas le choix, les deux critures se valent.
6.1.4 Exists versus Count
Les requtes effectuant un test dexistence sont quivalentes un comptage gal 0.
Listing6.5: Version Exists
select * from livres L
where not exists (select 1 from cmd_lignes CL where CL.NOLIVRE=L.NOLIVRE)
Listing6.6: Version 0=count(*)
select * from livres L
where 0 = (select count(*) from cmd_lignes CL where CL.NOLIVRE=L.NOLIVRE)
Nous allons tester ces requtes avec un index sur la colonne Nolivre de la table
cmd_lignes.
create index IS_cmd_lignes on cmd_lignes(nolivre);
MyISAM Exists Count
Temps 0,020s 1,110s
Key_read_requests 11915 166782
InnoDB Exists Count
Temps 22,940s 29,590s
Reads 8900 2606477
Oracle Exists Count
Temps 0,031s 0,031s
Consistent Gets 8909 8909
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 6 Techniques doptimisation standard des requtes 159
MS SQL Server Exists Count
Temps 0,062s 0,062s
Oracle et SQL Server considrent ces deux critures quivalentes, alors que MySQL
les voit bien diffrentes. On suppose que dans la version utilisant COUNT(*), il
dnombre toutes les occurrences pour tester lgalit 0, alors que la version uti-
lisant EXISTS sarrte la premire occurrence trouve.
6.1.5 Exists versus IN
Une sous-requte utilisant loprateur IN peut facilement tre convertie en sous-
requte utilisant loprateur EXISTS.
Nous allons tester ces requtes avec un index sur la colonne Nolivre de la table
cmd_lignes.
create index IS_cmd_lignes on cmd_lignes(nolivre);
Listing6.7: Version sous-requte IN
select sum(quantite) from cmd_lignes
where nolivre in (select nolivre from livres where editeur='Pearson')
Listing6.8: Version sous-requte Exists
select sum(quantite) from cmd_lignes cl
where exists (select nolivre from livres L
where editeur='Pearson' and CL.nolivre=L.nolivre )
MyISAM In Exists
Temps 14,010s 15,340s
Key_read_requests 5243442 5242448
InnoDB In Exists
Temps 7,420s 8,200s
Reads 2606480 5212684
Oracle In Exists Forage index
Temps 8,594s 8,594s 4,234s
Consistent Gets 4891735 4891735 2462067
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
160 tude et optimisation desrequtes Axe 2
Loptimiseur Oracle dcide de ne pas utiliser lindex. Si nous forons son usage
laide du hint /*+ index(cl is_cmd_lignes)*/, nous notons une amlioration des
performances.
Nous utilisons le hint /*+NO_QUERY_TRANSFORMATION*/ pour empcher la transfor-
mation des sous-requtes en anti-jointures qui ont un temps de rponse de lordre
0,34seconde.
MS SQL Server In ou Exists Forage index
Temps 0,625s 0,046s
Comme sous Oracle, nous devons forcer lutilisation de lindex avec le hint WITH
(INDEX(IS_CMD_LIGNES)).
Oracle et SQL Server considrent ces deux critures quivalentes, alors que MySQL
les voit diffrentes, lavantage tant loprateur IN sur les deux moteurs de MySQL.
6.1.6 Clause Exists * versus constante
On enseigne, depuis des annes, que lorsquon emploie des sous-requtes corrles
utilisant loprateur EXISTS, il faut retourner une constante (numrique ou texte)
dans la clause SELECT de la sous-requte. Est-ce seulement pour des raisons de clart
ou aussi de performances?
Listing6.9: Version Exists constante
select * from livres L
where not exists (select 1 from cmd_lignes CL where CL.NOLIVRE=L.NOLIVRE);
Listing6.10: Version Exists *
select * from livres L
where not exists (select * from cmd_lignes CL where CL.NOLIVRE=L.NOLIVRE);
Nous ne documentons pas le dtail des rsultats. On constate que les colonnes retour-
nes dans la sous-requte nont aucun impact sur les performances, alors quelles en
avaient sur danciennes versions dOracle.
Cette pratique de mettre une constante garde cependant tout son sens du point de
vue de la comprhension. Parfois, certains dveloppeurs mettent ici un champ par-
ticulier laissant ainsi croire quil y aurait une sorte de lien possible avec ce champ.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 6 Techniques doptimisation standard des requtes 161
6.1.7 Expressions sous requtes
Listing6.11: Requte utilisant une jointure
select c.nocmd,datecommande ,sum(montant) Total
from cmd c,cmd_lignes cl where cl.nocmd=c.nocmd and datecommande<to_
date('2004-04-18','yyyy-mm-dd')
group by c.nocmd, datecommande
Listing6.12: Requte utilisant une expression sous-requte
select nocmd,datecommande
,(select sum(montant) from cmd_lignes where nocmd=c.nocmd) Total
from cmd c where datecommande<to_date('2004-04-18','yyyy-mm-dd')
Nous choisissons ici une requte qui empche dappliquer le prdicat de la table
cmd directement la table cmd_lignes et qui ne retourne que 173lignes. En chan-
geant la date, nous testons une autre version qui ramne beaucoup plus de lignes
(132141).
Petite requte Grosse requte
MyISAM Jointure
Expression
sous-requte
Jointure
Expression
sous-requte
Temps 5,890s 0,160s 6,810s 1,950s
Reads 4873397 736 4873397 564513
Petite requte Grosse requte
InnoDB Jointure
Expression
sous-requte
Jointure
Expression
sous-requte
Temps 0,670s 0,670s 3,580s 4,030s
Reads 1001449 1000175 2264285 1632143
Petite requte Grosse requte
Oracle Jointure
Expression
sous-requte
Jointure
Expression
sous-requte
Temps 0,390s 0,060s 1,48s 1,51s
Consistent Gets 11490 3316 11490 117464
Petite requte Grosse requte
MS SQL Server Jointure
Expression
sous-requte
Jointure
Expression
sous-requte
Temps 0,125s 0,109s 0,812s 0,953s
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
162 tude et optimisation desrequtes Axe 2
Avec des requtes ramenant peu de lignes, l'avantage est aux expressions sous-
requtes. Avec des requtes ramenant beaucoup de lignes, l'avantage passe la ver-
sion jointure, sauf pour le moteur MyISAM qui a l'air plus l'aise avec l'utilisation
systmatique d'expressions sous-requtes. Seul l'optimiseur de SQL Server adapte
automatiquement son plan d'excution la solution la plus effcace, indpendam-
ment de l'criture. Nous avons donc utilis les hints loop join et merge join pour
effectuer ces tests.
6.1.8 Agrgats: Having versus Where
Quand cest possible, les conditions doivent tre places dans la clause WHERE plutt
que dans la clause HAVING qui est value aprs les oprations dagrgation. Cela
permet de profter dventuels index et rduit le volume traiter durant lopration
dagrgation.
Listing6.13: Requte utilisant Having (incorrecte)
select pays,ville,count(*) from clients t
group by pays,ville
having pays='France'
Listing6.14: Requte utilisant Where
select pays,ville,count(*) from clients t
where t.pays='France'
group by pays,ville
MyISAM Having Where
Temps 0,080s 0,030s
Reads 91109 45950
InnoDB Having Where
Temps 0,090s 0,050s
Reads 91132 45960
Oracle Having Where
Temps 0,047s 0,015s
Consistent Gets 624 624
MS SQL Server Having Where
Temps 0,046s 0,046s
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 6 Techniques doptimisation standard des requtes 163
Dans le plan dexcution de SQL Server, on voit quil dplace le prdicat de la
clause HAVING la clause WHERE, il ny a donc pas dimpact li lcriture. Par
contre, sur tous les autres SGBDR, limpact est notable et dautant plus que la slec-
tivit du prdicat est forte.
6.2 Bonnes et mauvaises pratiques
6.2.1 Mlange des types
Le mlange des types peut causer des grosses chutes de performances en disqua-
lifant des index cause de conversions (cast) ncessaires.
Dans la pratique, cest rarement une source de problme de performances mais plu-
tt une source de problme dexcution (message derreur) car le SGBDR fait les
conversions adquates. Cependant, une bonne pratique est de veiller faire explici-
tement les conversions adaptes.
6.2.2 Fonctions et expressions sur index
Lutilisation de fonctions (y compris de conversion) ou dexpressions sur des
colonnes indexes a pour effet de disqualifer les index.
select * from cmd_lignes
where 'C' || nocmd='C114826'
Cette requte entrane un parcours complet de la table alors quil serait pertinent
dutiliser lindex sur la colonne Nocmd. Sil nest pas possible de se passer de lex-
pression C + nocmd, les index sur fonction (voir Chapitre5, section5.2.2, "Index
sur fonction") peuvent apporter une solution ce type de problme. Ci-aprs, les
deux options possibles qui permettent cette requte de tirer proft de lindex sur le
champ Nocmd:
select * from cmd_lignes where nocmd=114826
ou:
Create Index IS_CMD_LIGNE_CNOCMD on CMD_LIGNES('C' || nocmd);
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
164 tude et optimisation desrequtes Axe 2
6.2.3 Impact de l'oprateur <> sur les index
Loprateur <> et ses quivalents!= et ^= ont un impact notable sur les index car il
ne les utilise pas. Illustrons ce comportement sur la requte suivante qui recherche la
date de la plus ancienne commande qui nest pas clture (Etatcommande <> C):
select min(datecommande) from cmd where etatcommande <>'C'
Nous avons pralablement cr un index et forc le calcul dun histogramme sur la
colonne Etatcommande:
create index is_cmd_etat on cmd(etatcommande);
execute dbms_stats.gather_table_stats(user,'cmd',cascade => true
,estimate_percent =>100,method_opt => 'for all columns size 100');
La distribution de la colonne Etatcommande est la suivante:
Etatcommande Nombre denregistrements
A 240
C 994700
I 5060
Cette requte traite moins de 1% des lignes et profterait donc dun index plac sur
la colonne Etatcommande, mais la prsence de loprateur <> lempche. Une solu-
tion permettant de contourner ce problme est de transformer cette requte. Cela se
fait soit par des galits:
select min(datecommande) from cmd where etatcommande in ('A','I')
soit par des intervalles excluant la valeur:
select min(datecommande) from cmd where etatcommande >'C' or etatcommande <'C'
Ces deux solutions utilisent lindex prsent sur la colonne Etatcommande et les
rsultats sont sans appel. Le temps dexcution passe de 125 ms 15 ms et les
Consistent Gets passent de 3194 58.
6.2.4 Rutilisation de vue
Parfois, une vue existante peut tre une bonne base pour faire une requte. Dans ce
cas, il faut vrifer que cette vue ne fait pas trop de travail inutile pour le besoin de la
requte que vous souhaitez crire. Assurez-vous quil ny a pas plus de tables en jeu
que celles que vous auriez utilises si vous naviez pas choisi la vue. Par exemple,
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 6 Techniques doptimisation standard des requtes 165
vous souhaitez calculer le chiffre daffaires journalier et vous disposez de la vue
suivante:
create view V_CA_JOURNALIER_PAYS as
Select cmd.datecommande,cli.pays, sum(cl.montant) CA
from cmd join cmd_lignes cl on cmd.nocmd=cl.nocmd
join clients cli on cmd.noclient=cli.noclient
group by cmd.datecommande,cli.pays
Vous trouvez donc que la solution la plus simple est de partir de cette vue en crivant
la requte suivante:
select datecommande,sum(CA)
from V_CA_JOURNALIER_PAYS
group by datecommande
Cette solution est certes pratique mais elle a linconvnient de faire une jointure
avec la table clients qui nest pas du tout ncessaire pour rpondre votre requte.
Lecot de votre requte passe ainsi de 7290 20136.
6.2.5 Utilisation de tables temporaires
Pour certaines requtes compliques (mettant en uvre de nombreuses tables), il
peut tre pertinent de travailler avec des tables temporaires. Ce choix est intressant
si le contenu de ces tables est interrog plusieurs fois afn de compenser le cot de
leur cration. Ces tables pourront tre indexes, de prfrence aprs linsertion des
donnes.
Sous Oracle, vous pouvez spcifer de ne pas tracer les oprations dans ce genre de
tables en utilisant la clause NOLOGGING lors de leur cration.
Create table xxx ( . . . ) NOLOGGING;
6.2.6 Utilisation abusive de SELECT *
Lutilisation de loprateur * dans la clause SELECT ramne tous les champs. Certains
dveloppeurs trouvent cela particulirement pratique mais ne mesurent pas forcment
les consquences que cela peut avoir.
Si vous avez besoin de ramener tous les champs de la table, il ny a rien dire,
Select * From LaTable est tout fait correct. Cependant, il y a de nombreux cas o
* est utilis alors que seuls certains champs sont ncessaires. Dans ce cas, on subit
inutilement:
une augmentation du volume transfr entre le client et le serveur;
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
166 tude et optimisation desrequtes Axe 2
une augmentation du volume mmoire ncessaire par le client et le serveur;
une augmentation des E/S disque du serveur sil y a des champs stocks dans des
segments spars (LOB, Text,etc.).
Prenez lhabitude de ne ramener que les donnes dont vous avez besoin en listant
les champs dans la clause SELECT. Il est frquent de trouver dans des standards de
codage linterdiction de loprateur*. La raison est que, si au moment du codage on
a besoin de tous les champs, ce ne sera peut-tre plus le cas si un champ est ajout
en phase de maintenance.
6.2.7 Suppression des tris inutiles
Les tris sont coteux, il faut donc sassurer quils sont ncessaires. Dans la requte
ci-aprs, sous Oracle, lajout du tri par Nom fait passer le cot de 171 1179 et
double le temps dexcution.
select * from clients order by nom
Si le mot cl DISTINCT est prsent, les consquences sont similaires car il ncessite
un tri.
6.2.8 Utilisation raisonne des oprations ensemblistes
Les oprations sur les ensembles (UNION, MINUS, INTERSECT) sont assez coteuses
et ne sont jamais transformes automatiquement par loptimiseur. Il faut y recourir
seulement quand cest la solution la plus adapte. Les oprations INTERSECT peuvent
souvent tre remplaces par une jointure et les oprations MINUS, par une anti-join-
ture ou un NOT IN. La suppression des oprations ensemblistes permettra dliminer
des tris intermdiaires et davoir un plan dexcution plus effcace. Les oprations
de type UNION sont souvent plus dlicates supprimer. Les transformations de lop-
ration INTERSECT sont illustres travers la requte suivante qui recherche les clients
qui ont achet le livre 1306 et qui ont pass moins de 50commandes.
Listing6.15: Version utilisant INTERSECT
select distinct c.noclient,c.nom,c.prenom,c.pays
from cmd_lignes cl join cmd on cl.nocmd=cmd.nocmd
join clients c on cmd.noclient=c.noclient
where cl.nolivre=1306
intersect
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 6 Techniques doptimisation standard des requtes 167
select c.noclient,c.nom,c.prenom,c.pays
from cmd join clients c on cmd.noclient=c.noclient
group by c.noclient,c.nom,c.prenom,c.pays
having count(*)<50
Temps dexcution: 0,703s, Consistent Gets: 6721, Cost: 10312
Listing6.16: Version utilisant une jointure
select A.*
from (select distinct c.noclient,c.nom,c.prenom,c.pays
from cmd_lignes cl join cmd on cl.nocmd=cmd.nocmd
join clients c on cmd.noclient=c.noclient
where cl.nolivre=1306 ) A
, (select c.noclient,c.nom,c.prenom,c.pays
from cmd join clients c on cmd.noclient=c.noclient
group by c.noclient,c.nom,c.prenom,c.pays
having count(*)<50 ) B
where a.noclient=b.noclient
Temps dexcution: 0,703s, Consistent Gets: 6721, Cost: 6945
Suite cette transformation, le gain nest pas forcment signifcatif, mais le fait
dutiliser une jointure permet de factoriser les jointures avec la table clients pr-
sente dans chacune des sous-requtes (voir Listing 6.17). Cette factorisation peut
amliorer les performances surtout si les ensembles retourns par les sous-requtes
sont gros.
Listing6.17: Version factorisant la jointure de la table clients
select c.noclient,c.nom,c.prenom,c.pays
from (select distinct cmd.noclient
from cmd_lignes cl join cmd on cl.nocmd=cmd.nocmd
where cl.nolivre=1306 ) A
, (select noclient
from cmd
group by noclient
having count(*)<50 ) B
, clients c
where a.noclient=b.noclient
and a.noclient=c.noclient
Temps dexcution: 0,531s, Consistent Gets: 7050, Cost: 2828
Illustrons une transformation de lopration MINUS sur la requte suivante qui
recherche les clients qui nont pas achet le livre 3307 et qui ont pass plus de
60commandes.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
168 tude et optimisation desrequtes Axe 2
Listing6.18: Version utilisant MINUS
select c.noclient,c.nom,c.prenom,c.pays
from cmd join clients c on cmd.noclient=c.noclient
group by c.noclient,c.nom,c.prenom,c.pays
having count(*)>60
MINUS
select distinct c.noclient,c.nom,c.prenom,c.pays
from cmd_lignes cl join cmd on cl.nocmd=cmd.nocmd
join clients c on cmd.noclient=c.noclient
where cl.nolivre=3307
Temps dexcution: 0,672s, Consistent Gets: 7572, Cost: 10312
Listing6.19: Version utilisant une anti-jointure
select A.*
from (select c.noclient,c.nom,c.prenom,c.pays
from cmd join clients c on cmd.noclient=c.noclient
group by c.noclient,c.nom,c.prenom,c.pays
having count(*)>60 ) A
left outer join
(select distinct c.noclient,c.nom,c.prenom,c.pays
from cmd_lignes cl join cmd on cl.nocmd=cmd.nocmd
join clients c on cmd.noclient=c.noclient
where cl.nolivre=3307 ) B
on a.noclient=b.noclient
where b.noclient is null
Temps dexcution: 0,672s, Consistent Gets: 7572, Cost: 6945
Tout comme avec INTERSECT, le fait dutiliser une jointure nous permet de factoriser
les jointures avec la table clients prsente dans chacune des sous-requtes.
Listing6.20: Version utilisant une anti-jointure factorisant la jointure de la table clients
select c.noclient,c.nom,c.prenom,c.pays
from (select noclient
from cmd
group by noclient
having count(*)>60 ) A
left outer join
(select noclient
from cmd_lignes cl join cmd on cl.nocmd=cmd.nocmd
where cl.nolivre=3307 ) B
on a.noclient=b.noclient
, clients c
where A.noclient=c.noclient
Temps dexcution: 0,516s, Consistent Gets: 7899, Cost: 2827
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 6 Techniques doptimisation standard des requtes 169
6.2.9 Union versus Union ALL
Les oprateurs UNION et UNION ALL sont trs proches. La seule diffrence est que, si
une donne est prsente dans les deux ensembles, elle napparatra quune fois dans
le cas de loprateur UNION. Mais il y a un pige: si la donne apparat deux fois dans
un des ensembles, elle napparatra aussi quune seule fois dans lensemble rsultat.
On peut donc en dduire que
UNION = DISTINCT UNION ALL
Comme nous lavons vu au paragraphe prcdent, ce DISTINCT a un cot car il
provoque lexcution dun tri.
Loprateur UNION est souvent utilis tort la place dUNION ALL, qui est moins
connu.
Figure6.1
Plan d'excution
utilisant UNION.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
170 tude et optimisation desrequtes Axe 2
Figure6.2
Plan d'excution
utilisant UNION ALL.
Nous constatons dans ces traces dexcution que le cot, les Consistent Gets et le
temps dexcution augmentent de faon signifcative. On voit aussi quil y a un tri
de plus. Plus lensemble rsultat est gros, plus limpact sera fort.
6.2.10 Count(*) versus count(colonne)
La fonction COUNT a pour objet de compter les valeurs non nulles dune colonne,
mais elle est souvent utilise pour compter le nombre denregistrements. Dans ce
cas, la notation COUNT(*) est prconise. Cependant, par mconnaissance ou par
habitude, certaines personnes continuent utiliser COUNT(colonne).
Lutilisation de COUNT(*) permet loptimiseur de ne pas accder lenregistrement
entier sil nen a pas besoin pour rpondre la requte car il peut le faire avec des
index.
La requte ci-aprs a un cot de 27 et naccde qu lindex de la cl primaire:
select count(*) from clients
Alors que cette requte, qui retourne le mme rsultat si on considre que les noms
sont remplis, provoque un parcours complet de la table et a un cot de 171:
select count(nom) from clients
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 6 Techniques doptimisation standard des requtes 171
Cependant, si la colonne est note obligatoire (NOT NULL), alors loptimiseur conver-
tit automatiquement COUNT(colonne) en COUNT(*).
6.2.11 Rduction du nombre de parcours des donnes
Plutt que parcourir n fois un ensemble de donnes pour rpondre n questions,
on essaiera de ne le parcourir quune fois en rpondant simultanment aux nques-
tions. Linstruction CASE sera utile cette fn puisquelle permet davoir une syntaxe
proche des clauses WHERE.
Listing6.21: Requte provoquant trois parcours des donnes
SELECT '<2000' categ,COUNT (*) FROM cmd_lignes WHERE montant < 2000
union all
SELECT '2000-4000' categ,COUNT (*) FROM cmd_lignes WHERE montant BETWEEN 2000
AND 4000
union all
SELECT '>4000' categ,COUNT (*) FROM cmd_lignes WHERE montant >4000 ;
CATEG COUNT(*)
--------- ----------
<2000 2604322
2000-4000 2146
>4000 9
Listing6.22: Requte ne parcourant qu'une seule fois les donnes
SELECT count (CASE WHEN montant < 2000 THEN 1 END) nbrinf2k,
count (CASE WHEN montant BETWEEN 2000 AND 4000 THEN 1 END) nbr2k4k,
count (CASE WHEN montant > 4000 THEN 1 END) nbrsup4k
FROM cmd_lignes;
NBRINF2K NBR2K4K NBRSUP4K
---------- ---------- ----------
2604322 2146 9
Note: la fonction COUNT ne compte que les valeurs non nulles et labsence de clause
ELSE quivaut ELSE NULL. Nous aurions obtenu le mme rsultat avec la fonction
SUM, mais nous avons un meilleur temps de rponse en comptant les valeurs non
nulles.
La seconde requte ne demande quun seul parcours de la table au lieu de trois pour
la premire. Elle sera ainsi gnralement plus performante. Si la table est grande et
ncessite des accs disques, lcart sera dautant plus net. Si la table peut tenir en
mmoire, lcart sera moindre, voire invers.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
172 tude et optimisation desrequtes Axe 2
Dans lexemple que nous prsentons ici, la table tient en mmoire. De ce fait, sous
Oracle et SQL Server le gain nest pas du tout signifcatif; par contre, sous MySQL
lcart est signifcatif.
6.2.12 LMD et cls trangres
Les contraintes dintgrit rfrentielle implmentes par des cls trangres
(Foreign Key) sont contrles dans le sens fls parent, lors de linsertion de donnes
dans les tables flles.
Lors des UPDATE de cl ou des DELETE dans la table rfrence (table parente de la
relation), le SGBDR contrle dans les tables flles si des enregistrements existent,
soit pour interdire lopration, soit pour propager leffacement ou la mise jour si
les options ON CASCADE DELETE ou ON CASCADE UPDATE sont actives. Dans les deux
cas, pour chaque cl impacte, le SGBDR effectue une requte dans la table flle.
La table parente est, par conception, systmatiquement indexe. Ainsi, le contrle
de la prsence de la cl dans la table rfrence lors de linsertion dune donne dans
la table flle sera performant, mme si, sur de gros volumes, le cot peut devenir
signifcatif par rapport labsence de contrainte de type cl trangre.
Par contre, sur les tables flles, les champs sont moins souvent indexs, ce qui
peut causer de gros problmes de performances en cas dopration portant sur des
volumes importants.
Dans notre base exemple, imaginons que la suppression dun client provoque leffa-
cement de ses commandes et des lignes de commandes associes. Labsence dindex
sur les colonnes flles pourrait causer une norme chute des performances en cas de
suppression de centaines de clients. On note que, par conception, sur les relations
dpendantes (comme ici entre cmd et cmd_lignes), la cl de la table parente se
retrouve dans la cl de la table flle et est donc indexe.
Lors dun test que nous avons effectu, nous avons constat un ratio de 125
(5 secondes contre 650 secondes) ; par ailleurs, nous avons dj eu loccasion de
voir chez un client un DELETE durer deux heures au lieu de quelques secondes sur des
grandes tables. Attention, le cot des oprations impliques par du LMD nest pas
affch, ni valu dans le plan dexcution des instructions LMD.
Une bonne pratique consiste indexer les colonnes flles des relations 1N, sur-
tout si les parents sont mouvements. Ces index sont frquemment pertinents pour
laspect interrogation des donnes.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 6 Techniques doptimisation standard des requtes 173
6.2.13 Suppression temporaire des index et des CIR
Pour certaines oprations de chargement massif de donnes, il peut parfois tre
pertinent de supprimer les index et les CIR (principalement les Foreign Key et les
cls primaires) et de les rcrer une fois lopration termine. Cette solution permet
dconomiser la rorganisation dynamique de lindex et damliorer le temps nces-
saire au contrle des contraintes. Cependant, elle nest pas toujours intressante et
doit donc tre value au cas par cas (comme toute solution visant amliorer les
performances).
En cas de dsactivation de contraintes, il faudra veiller charger des donnes qui les
respectent. Sinon, il ne sera pas possible de les ractiver par la suite, ce qui pourra
poser des problmes de qualit des donnes. Si les cls primaires ne peuvent pas
tre recres cause de la prsence de doublons de cls, les index normalement
associs aux cls ne seront pas crs non plus, ce qui aboutira une probable chute
des performances.
6.2.14 Truncate versus Delete
La commande TRUNCATE permet de vider entirement le contenu dune table. Elle
est donc fonctionnellement quivalente la commande DELETE sans clause WHERE.
Elle fait partie des commandes LDD (langage de dfnition des donnes) et travaille
au niveau des structures de donnes plutt quau niveau des enregistrements. Elle
est ainsi bien plus performante car elle ne ncessite pas lusage des fonctionnalits
de journalisation et des transactions. Cependant, faire partie des commandes LDD
lui impose quelques limites et induit quelques consquences:
Les mmes privilges que pour faire un DROP de la table sont requis (le privilge
DELETE ne sufft pas).
La table tronque ne peut tre rfrence daucune Foreign Key.
Il est impossible de faire un ROLLBACK (cela provoque dailleurs un COMMIT
implicite).
6.2.15 Impacts des verrous et des transactions
Le fait de pouvoir travailler plusieurs personnes sur une mme base grant les
notions de transactions isoles a des consquences techniques normes du point de
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
174 tude et optimisation desrequtes Axe 2
vue du SGBDR (Oracle, SQL Server, moteur InnoDB de MySQL). Nous pourrions
consacrer un chapitre entier ce sujet, mais cette section rsume les points cls.
Par exemple, lors de la modifcation dun enregistrement:
Si un ROLLBACK est excut, il faut remettre lancienne valeur.
Tant quun COMMIT nest pas excut:
les autres utilisateurs voient les anciennes donnes;
si un autre utilisateur essaie de modifer les donnes, l'opration provoquera
une erreur ou sera bloque grce la gestion des verrous.
Tout cela est gr grce des mcanismes de verrouillage et de gestion des versions
de lignes (MVCC, Multi Version Concurrency Control), qui sont trs volus, ce qui
a donc un cot en termes de ressources.
La norme SQL propose quatre niveaux disolation qui ont des impacts diffrents sur
les performances:
Read Uncommitted. Ne gre pas les versions de lignes. On voit les dernires
oprations mme si elles ne sont pas valides, on parle alors de "lectures sales"
(dirty read). Ce mode nest pas recommand, mais cest le seul mode de travail
connu des SGBDR ne grant pas les transactions (moteur MyISAM de MySQL
par exemple).
Read Committed. On ne voit que ce qui est valid. Cest le mode de fonction-
nement par dfaut des SGBDR grant les transactions.
Repeatable Read. Si une mme transaction rexcute une requte, elle verra
toujours les mmes donnes, mme si des changements ont t valids; cependant,
de nouveaux enregistrements valids pourront apparatre.
Serializable. Si une mme transaction rexcute une requte, elle verra toujours
les mmes donnes.
Oracle gre seulement les modes Read Committed et Serializable au moyen des
instructions suivantes:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Oracle propose aussi une variante plus conomique en ressource de Serializable en
empchant les modifcations depuis la transaction courante laide de linstruction:
SET TRANSACTION ISOLATION LEVEL READ ONLY;
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 6 Techniques doptimisation standard des requtes 175
Sous MySQL, avec le moteur InnoDB les quatre niveaux sont disponibles, mais en
fait Repeatable Read et Serializable sont quivalents.
SQL Server propose et implmente les quatre niveaux.
De faon gnrale, pour viter des impacts ngatifs sur les performances lies ces
mcanismes, appliquez les rgles suivantes:
Faites des transactions courtes.
Si vous modifez de gros volumes de donnes, essayez de dcomposer lopration
en plusieurs transactions.
Faites souvent des COMMIT.
Ne verrouillez pas les donnes outrance.
Par ailleurs, si vous ne craignez pas de mauvaise surprise avec les critures non vali-
des, vous pouvez utiliser, lorsque cela est disponible, Read Uncommited, le niveau
disolation minimal. Ce niveau peut affcher des incohrences dans les donnes si
les transactions font des modifcations dans plusieurs tables simultanment. Il est
cependant adapt de nombreuses requtes dans de nombreux environnements.
Ilmrite dtre tudi sil vous apporte des gains signifcatifs.
6.2.16 Optimisation du COMMIT
Linstruction COMMIT permet de terminer une transaction et dans de nombreux cas ne
ncessite pas de prcautions particulires. Nanmoins, dans des traitements par lot
(batch) qui manipulent de gros volumes, quelques optimisations peuvent tre appor-
tes. En effet, lappel de COMMIT valide la transaction et la rend ainsi durable (cest
le D dACID, voir encadr Info ci-aprs). Pour cela, la transaction est crite dans le
fchier journal de transactions provoquant une E/S.
Une premire piste doptimisation consiste jouer sur la frquence des COMMIT. En
effet, lorsque vous modifez un million denregistrements, vous pouvez dcider de
faire un COMMIT:
chaque ligne modife;
la fn du traitement;
de faon priodique.
Si vous avez le choix (ce qui nest pas toujours le cas), il est prfrable de faire des
COMMIT rguliers portant sur des volumes de quelques dizaines quelques centaines
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
176 tude et optimisation desrequtes Axe 2
denregistrements. Un COMMIT chaque ligne modife est coteux de mme quun
COMMIT portant sur un gros volume de donnes.
Une seconde piste consiste prendre quelques liberts avec laspect durable de la
transaction, en laissant les critures disque se faire de faon asynchrone au COMMIT
et non pas de faon bloquante. Cest possible avec les options NOWAIT et BATCH de
linstruction COMMIT. Il ne faut pas utiliser ces options si la criticit des donnes ne
permet pas de prendre de libert avec laspect ACID de la transaction.
INFO
Une transaction doit tre ACID, c'est--dire rpondre aux caractristiques suivantes:
Atomique. La totalit ou aucune des oprations composant la transaction doit tre valide.
Consistante. La base est dans un tat cohrent la fn de la transaction qu'elle soit vali-
de ou annule.
Isol. La transaction n'est pas visible par les autres transactions tant qu'elle n'est pas vali-
de (voir la section prcdente).
Durable. Une fois la transaction valide, elle doit persister mme en cas d'incident matriel.
6.2.17 DBLink et vues
Sous Oracle, lexcution de requtes ayant des jointures entre des tables adresses
par un DBLink, comme illustr dans la requte ci-aprs, pose souvent des problmes
de performances. Une solution de contournement consiste crer une vue effectuant
la jointure dans la base distante et interroger cette vue travers le DBLink.
Listing6.23: Requte avec une jointure travers un DBLink
select count(*)
from cmd@RemoteBase1 c,cmd_lignes@RemoteBase1 cl
where c.nocmd = cl.nocmd and noclient=41256
Listing6.24: Requte avec une jointure dans une vue et interrogation de la vue travers
un DBLink
-- Cration d'une vue sur la base distante.
Create view Vue1 AS
select cl.*,c.noclient,c.datecommande,c.etatcommande
from cmd c,cmd_lignes cl
where c.nocmd = cl.nocmd ;
-- Requte locale faisant reference la vue sur la base distante.
select count(*) from Vue1@RemoteBase1 where noclient=41256
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
7
Techniques d'optimisation
desrequtes avances
7.1 Utilisation des hints sous Oracle
Les hints (indications en anglais) sont des conseils que lon donne loptimiseur
pour lorienter dans le choix dun plan dexcution. Ce dernier sera du coup diff-
rent de celui quil aurait choisi normalement en estimant que ctait le moins co-
teux pour excuter la requte demande. Lutilisation des hints peut compenser une
erreur destimation de loptimiseur, mais un hint forcera un chemin daccs, mme
sil devient compltement aberrant. Il faut bien avoir en tte que loptimiseur, bien
quil ne soit pas parfait, sadapte alors quun hint crit dans une requte ne sadap-
tera pas tant que vous naurez pas rcrit la requte.
Loptimiseur nest pas oblig de suivre le conseil (ce qui est plutt rare). Sil ne
comprend pas un hint, il lignore sans affcher aucun message derreur (ce qui peut
parfois donner le sentiment quil ne suit pas le conseil).
Les hints peuvent conduire des gains signifcatifs et des chutes de performances
dsastreuses. Ils ne sont gnralement pas ncessaires, ils doivent tre mis en uvre
avec prcaution et parcimonie, vous ne devez les utiliser quen dernier recours et en
parfaite connaissance de cause.
Avec les versions plus anciennes dOracle, les choses taient diffrentes, loptimi-
seur tait moins performant et lutilisation des hints tait un passage incontournable.
Aujourdhui, ils peuvent certes encore permettre des optimisations, mais cela se res-
treint gnralement au cas, plutt rare, o loptimiseur fait une mauvaise valuation.
Le reste du temps, les hints sont plutt un risque.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
178 tude et optimisation desrequtes Axe 2
Nous allons tudier rapidement les plus utiles, mais il ne faut surtout pas en mettre
partout.
MS SQL Server
Tout comme sous Oracle, on retrouve le concept de hint sous SQL Server. Ils font, par
contre, pleinement partie de la syntaxe du SQL et peuvent provoquer des erreurs s'ils
sont syntaxiquement incorrects. Microsoft met en garde de la mme faon qu'Oracle sur
leur mise en uvre qui n'est gnralement pas ncessaire et qui doit tre rserve des
administrateurs et des dveloppeurs expriments.
Trois types de hints sont disponibles:
Les hints de jointures. Placs dans les clauses de jointures, ils permettent de spcifer le
type de jointure (LOOP, HASH, MERGE, REMOTE).
table1 inner hash join table2
table1 left outer merge join table2
Les hints de requtes. Ils sont placs la fn de la requte dans la clause OPTION. De
nombreuses options sont disponibles.
Select ... from ... OPTION (MAXDOP 4)
Select ... from ... OPTION (FORCE ORDER)
Les hints de tables. Placs aprs le nom de la table dans la clause WITH, ils permettent,
entre autres, d'agir sur le niveau d'isolation, les verrous ou les index utiliss.
Select ... from table1 WITH (SERIALIZABLE , INDEX(myindex) )
Consultez la documentation pour plus d'informations sur les hints. Soyez toujours trs
prudent lorsque vous mettez en uvre un hint.
MySQL
On retrouve aussi sous MySQL le concept de hint mais le choix est plus modeste. Ils sont
intgrs la syntaxe et se dcomposent en trois types:
Le hint de jointure. Plac dans les clauses de jointures, il permet de spcifer l'ordre de
jointure de type INNER l'aide du mot cl STRAIGHT_JOIN.
table1 STRAIGHT_JOIN table2 on ...
Les hints de requtes. Ils sont placs juste aprs le mot cl SELECT. Les valeurs pos-
sibles sont : HIGH_PRIORITY, STRAIGHT_JOIN, SQL_SMALL_RESULT, SQL_BIG_RESULT,
SQL_BUFFER_RESULT, SQL_CACHE, SQL_NO_CACHE, SQL_CALC_FOUND_ROWS
Select SQL_NO_CACHE * from table1
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 179
Les hints de tables. Placs aprs le nom de la table, ils infuent sur les index utiliss ou
pas. La syntaxe est la suivante:
{USE | IGNORE | FORCE } {INDEX|KEY} [{FOR {JOIN|ORDER BY|GROUP
BY}] ([index_list])
Select ... from table1 USE INDEX(myindex)
Consultez la documentation pour plus d'informations sur les hints. Soyez toujours trs
prudent lorsque vous mettez en uvre un hint.
7.1.1 Syntaxe gnrale
Les hints sont placs dans un commentaire qui suit le mot cl de linstruction
(SELECT, INSERT, UPDATE, DELETE, MERGE).
Le commentaire est de la forme /*+ monhint */ ou --+ monhint:
Select /*+ monhint */ nom from clients . . .
Attention, sil y a un espace avant le +, le hint ne sera pas considr comme tel.
Si le hint est incorrect (syntaxiquement ou smantiquement), il est simplement
ignor.
Les hints peuvent avoir frquemment des paramtres qui sont des noms de table et
dindex. Dans le cas des tables, il faut en fait mentionner lalias associ la table
et non pas la table elle-mme, puisquelle peut apparatre plusieurs fois dans la
requte. Rappel: quand aucun alias nest spcif pour une table, lalias par dfaut
est le nom de la table. Sil y a plusieurs paramtres dans le hint, ils sont spars par
un espace (pas de virgule).
Select /*+ monhint(t) */ nom from client t . . .
Il est possible de spcifer plusieurs hints en les crivant les uns derrire les autres
spars par un espace.
select /*+index(cmd is_cmd_client) no_index(cli pk_clients) */
count(datecommande)
from clients cli join cmd on cli.noclient=cmd.noclient
7.1.2 Les hints Optimizer Goal
All_Rows. Spcife que cette requte privilgiera la rcupration de toutes les lignes
(voir Chapitre1, section1.4.2, "Loptimiseur CBO (Cost Based Optimizer)").
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
180 tude et optimisation desrequtes Axe 2
First_Rows(n). Spcife que cette requte privilgiera la rcupration des n pre-
mires lignes. Ce hint encouragera lutilisation des index mme pour des gros
ensembles scanner. Dans la requte ci-aprs, lindex sur le champ Livre est utilis
si on spcife le hint, sinon il ne lest pas:
select /*+ First_Rows(10)*/ * from cmd_lignes t
where nolivre<102354
7.1.3 Les hints Access Path
Full (table_alias). Permet de forcer un parcours complet dune table au lieu
dutiliser un index.
Index (table_alias Nom_index). Permet de forcer lutilisation dun index en partic-
ulier lors de laccs une table. Ce hint est le plus utilis car il empche loptimiseur
dcarter, tort, un index sil y a des erreurs destimation des cardinalits.
select /*+index(cmd is_cmd_client) */ *
from cmd where noclient >10000
No_Index (table_alias Nom_index). Interdit lutilisation dun index particulier
lors de laccs une table.
select /*+no_index(cmd is_cmd_client) */ *
from cmd where noclient >10000000
Index_FFS (table_alias Nom_index). Permet de forcer un Fast Full Scan sur un
index.
No_Index_FFS (table_alias Nom_index). Interdit un Fast Full Scan sur un index.
Index_SS (table_alias Nom_index). Permet de forcer un Skip Scan sur un index.
No_Index_SS (table_alias Nom_index). Interdit un Skip Scan sur un index.
Index_RS (table_alias Nom_index). Permet de forcer un Range Scan sur un index
(napparat pas dans la documentation offcielle).
INDEX_COMBINE(table_alias Nom_index1 Nom_index2 ). Force une combinaison
de type bitmap de plusieurs index B*Tree (voir Figure5.8, la section5.2.4, "Index
bitmap").
select /*+ INDEX_COMBINE(clients is_clients_pays is_clients_nom ) */ *
from clients where pays ='France' and nom = 'Roberts'
INDEX_JOIN (table_alias Nom_index1 Nom_index2 ). Force une combinaison par
jointure de plusieurs index.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 181
7.1.4 Les hints Query Transformation
NO_QUERY_TRANSFORMATION. Interdit toutes les transformations de requtes.
USE_CONCAT. Transforme des prdicats OR en concatnation (une sorte dUNION).
select /*+ USE_CONCAT */ * from cmd_lignes
where nocmd=14827 or nolivre=3289
La requte prcdente ressemble celle-ci ( la gestion de doublons prs):
select * from cmd_lignes where nocmd=14827
union
select * from cmd_lignes where nolivre=3289
NO_EXPAND. Interdit la transformation des prdicats OR en concatnation. Cest
loppos du hint USE_CONCAT.
REWRITE. Force lutilisation des vues matrialises sil y en a de disponibles.
NO_REWRITE. Interdit lutilisation des vues matrialises.
MERGE (query_block). Force lintgration dune vue dans le schma dexcution
principal.
select /*+MERGE(C)*/ cli.noclient,nom, C.Nbr
from clients cli,
(select noclient,count(*) Nbr
from cmd group by noclient) C
where cli.noclient=C.noclient;
Limpact sur le plan dexcution de la requte prcdente est de supprimer la cration
intermdiaire de la vue.
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)|
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 45000 | 1713K| | 2390 (3)|
|* 1 | HASH JOIN | | 45000 | 1713K| 1104K| 2390 (3)|
| 2 | TABLE ACCESS FULL | CLIENTS | 45000 | 571K| | 171 (1)|
| 3 | VIEW | | 45156 | 1146K| | 2083 (3)|
| 4 | HASH GROUP BY | | 45156 | 220K| 12M| 2083 (3)|
| 5 | TABLE ACCESS FULL| CMD | 1000K| 4882K| | 890 (2)|
-----------------------------------------------------------------------------
Dans le plan dexcution ci-aprs (avec le hint MERGE), on constate que la jointure est
faite entre cmd et clients et ensuite seulement le GROUP BY est effectu.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
182 tude et optimisation desrequtes Axe 2
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)|
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 996K| 40M| | 12663 (1)|
| 1 | HASH GROUP BY | | 996K| 40M| 99M| 12663 (1)|
|* 2 | HASH JOIN | | 996K| 40M| 2200K| 1703 (1)|
| 3 | TABLE ACCESS FULL | CLIENTS | 45000 | 1669K| | 171 (1)|
| 4 | INDEX FAST FULL SCAN| IS_CMD_CLIENT | 1000K| 4882K| | 611 (1)|
-------------------------------------------------------------------------------------
NO_MERGE (query_block). Empche lintgration dune vue dans le schma dex-
cution principal. Cest loppos du hint MERGE.
UNNEST. Permet de faire des transformations de type boucle imbrique vers jointure.
NO_UNNEST. Empche les transformations de type boucle imbrique vers jointure qui
sont, trs souvent, effectues lorsquil y a des sous-requtes.
PUSH_PRED(query_block) / NO_PUSH_PRED(query_block). Force ou interdit
lapplication dun prdicat dans une vue.
7.1.5 Les hints de jointure
LEADING. Permet de spcifer la table menante dans une jointure.
select /*+leading (cmd cli) */ cli.noclient,nom, cmd.datecommande
from clients cli,cmd
where cli.noclient=cmd.noclient
and cli.noclient between 100000 and 100020
ORDERED. Permet de spcifer que les jointures doivent tre faites dans lordre dappa-
rition dans la clause FROM.
USE_NL,NO_USE_NL. Force ou interdit une jointure par boucles imbriques (Nested
Loop).
USE_NL_WITH_INDEX. Force une jointure par boucles imbriques seulement si un
index est prsent sur la table jointe. Ce hint sera sans effet si lindex disparat ou est
invalid. En effet, limpossibilit dutiliser un index pourrait avoir des consquences
dsastreuses en termes de performances: une boucle imbrique sur une grosse table
non indexe a des performances catastrophiques car elle provoque un parcours
complet de la table pour chaque valeur de la table menante.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 183
USE_MERGE, NO_USE_MERGE. Force ou interdit une jointure par Sorted Merge.
USE_HASH, NO_USE_HASH. Force ou interdit une jointure par table de hachage.
7.1.6 Autres hints
Il existe une srie de hints destins au paralllisme que nous tudierons la
s ection7.2.1 de ce chapitre.
CACHE (table_alias). Dsigne la table comme trs utilise pour quelle reste
longtemps dans le cache. Cest le comportement par dfaut pour les petites tables.
NOCACHE (table_alias). Dsigne la table comme peu utilise pour quelle quitte
rapidement le cache. Cest le comportement par dfaut pour les grosses tables.
QB_NAME. Permet de spcifer un bloc pour y appliquer un hint.
SELECT /*+ QB_NAME(qb) FULL(@qb c) */ *
FROM clients c WHERE nom = 'SMITH';
DRIVING_SITE. Permet dinfuer sur lexcution de requtes utilisant des DBLink et
des bases distantes.
DYNAMIC_SAMPLING (table_alias niveau_echantillonnage). Permet de faire un
chantillonnage dynamique des donnes pour complter les informations fournies
par les statistiques, afn de les ajuster avec les prdicats de la requte (voir Cha-
pitre5, section5.1.3, "Slectivit, cardinalit, densit").
7.2 Excution parallle
Il sagit ici de faire excuter une requte par plusieurs processeurs de faon paral-
lle. Nous nallons pas entrer dans le dtail de tout ce quil est possible de faire avec
lexcution parallle, mais juste donner un aperu.
Comme vous pouvez vous en douter, ce dcoupage en sous-tches a un certain cot
dorganisation. De plus, lexcution parallle a pour caractristique de sexcuter
principalement en faisant des lectures disques plutt quen utilisant le cache de
donnes. Cela conforte lide que cette opration est plutt destine travailler
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
184 tude et optimisation desrequtes Axe 2
sur de gros volumes. Ce type doptimisation ne sera pertinent que dans les cas
suivants:
Il y a plusieurs processeurs disponibles.
Il ny a pas de goulet dtranglement au niveau du disque dur.
Il y a suffsamment de choses faire pour que la mise en place du paralllisme
soit compense par le gain li ce dernier.
Lutilisation du paralllisme sur des cas non adapts provoquera un ralentissement
des oprations. Lexcution parallle est particulirement adapte des tables parti-
tionnes, rparties sur des disques diffrents.
Les oprations concernes par la paralllisation sont:
les requtes interrogations de type SELECT;
les requtes de manipulation des donnes (LMD: UPDATE, DELETE sur partitions
diffrentes et INSERT sur requte);
certaines oprations de LDD.
Lexcution parallle peut tre confgure au niveau de la session pour les trois types
doprations laide des paramtres suivants:
PARRALEL QUERY
PARRALEL DML
PARRALEL DDL
Les paramtres de paralllismes peuvent avoir une des trois valeurssuivantes:
ENABLE. Les fonctions de paralllisme seront utilises si elles sont spcifes par
un hint dune requte ou au niveau dun objet manipul.
DISABLE. Les fonctions de paralllisme ne seront pas utilises.
FORCE. Permet de forcer un niveau de paralllisme.
Par dfaut, le paralllisme est confgur ainsi:
PARRALEL QUERY = ENABLE
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 185
PARRALEL DML = ENABLE
PARRALEL DDL = DISABLE
Si vous souhaitez spcifer des hints de paralllisme dans les requtes DML, vous
devrez dabord excuter linstruction suivante:
alter session enable parallel dml;
Lexcution parallle peut tre confgure au niveau de chaque requte comme montr
ci-aprs:
select /*+ PARALLEL(c , 4) */max(C.DATECOMMANDE) from cmd c;
insert /*+ parallel (Cmd2009,4,1) */ into Cmd2009
select * from cmd Where datecommande<To_Date('2010','YYYY');
alter index IS_CMD_CLIENT rebuild parallel 4;
Lexcution parallle peut tre confgure au niveau des objets. Ainsi, toute opra-
tion sur ces objets sera paralllise sans que vous ayez le spcifer au niveau de
lopration.
ALTER TABLE cmd PARALLEL (DEGREE 4);
Les oprations parallles prennent gnralement un paramtre, nomm "degr de
paralllisme" (DOP, degree of parallelism), qui dfnit le nombre de sous-tches
concurrentes qui composeront lopration. Il est important de choisir un DOP en
adquation avec le matriel. Cest inutile, voire ineffcace, de spcifer un DOP
suprieur au nombre dunits de traitement (nombre de CPU nombre de curs
par CPU).
7.2.1 Les hints de paralllisme
PARALLEL(table_alias , degr //). Permet de spcifer un niveau de paralllisme
pour les accs une table.
NO_PARALLEL (table_alias). Permet de dsactiver le paralllisme pour les accs
une table.
PARALLEL_index (table_alias , idx,degr). Permet de spcifer un niveau de
paralllisme sur les Index Scan.
NO_PARALLEL_index (table_alias). Permet de dsactiver le paralllisme sur les
Index Scan.
PQ_DISTRIBUTE. Permet dinfuer sur les modes de communication entre les sous-
tches pour effectuer les jointures parallles.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
186 tude et optimisation desrequtes Axe 2
MS SQL Server
SQL Server gre aussi le paralllisme de faon assez analogue Oracle. Cependant, il est
bien plus effcace sur la paralllisation des petites requtes et active d'ailleurs par dfaut
ce comportement (sauf sur les ditions express).
Le hint MAXDOP permet d'infuer sur le niveau de paralllisme. La valeur1 permet de le
dsactiver.
Exemple de plan d'excution d'une requte avec un degr de paralllisme 4:
select sum(quantite) from cmd_lignes
option (maxdop 4)
Figure7.1
Plan d'excution
d'une requte
paralllise sous
MS SQL Server.
MySQL
MySQL ne propose pas de solution pour exploiter plusieurs processeurs dans une mme
requte.
7.3 Utilisation du SQL avanc
Certaines fonctions avances permettent de faire des requtes quil tait quasiment
impossible de faire en SQL conventionnel ou alors au prix dune grosse chute des
performances. La plupart ont t introduites en version8i ou 9i dOracle, dans les
dernires versions de SQL Server et ne sont pas disponibles sous MySQL.
7.3.1 Les Grouping Sets
Ils sont disponibles depuis Oracle 9i et SQL Server 2008.
Les Grouping Sets permettent dutiliser les fonctions dagrgats sur plusieurs
groupes diffrents dans la mme requte. La requte suivante:
Select JOB,ENAME, count(*) From BIGEMP
Group by Grouping Sets ((JOB), (ENAME))
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 187
quivaut smantiquement :
Select JOB,NULL ENAME, count(*) From BIGEMP
Group by JOB
union all
Select NULL,ENAME, count(*) From BIGEMP
Group by ENAME
et produit le rsultat ci-aprs:
JOB ENAME COUNT(*)
--------- ---------- ----------
ALLEN 100001
JONES 100001
FORD 100001
CLARK 100001
MILLER 100001
SMITH 100001
WARD 100001
MARTIN 100001
SCOTT 100001
TURNER 100001
ADAMS 100001
BLAKE 100001
KING 100001
JAMES 100001
SALESMAN 400004
CLERK 400004
PRESIDENT 100001
MANAGER 300003
ANALYST 200002
19 rows selected
En termes de performances, GROUPING SETS devrait normalement tre deux fois plus
rapide que deux requtes GROUP BY successives puisquon ne parcourt quune fois
lensemble de donnes. Dans les faits, lestimation faite par loptimiseur indique
que le cot est deux fois moindre pour la requte utilisant GROUPING SETS que pour
la requte utilisant les GROUP BY simples. Cependant, lcart nest plus que de 15%
pour les Consistent Gets, et la tendance sinverse en temps dexcution: la requte
utilisant des GROUP BY simples est plus rapide sur Oracle. Sur SQL Server, la requte
utilisant GROUPING SETS est plus rapide de 20%.
Il conviendra, encore plus que dhabitude, dvaluer cette solution dans votre
contexte afn de juger de son rel intrt.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
188 tude et optimisation desrequtes Axe 2
7.3.2 Rollup Group By
Il est disponible sur SQL Server, MySQL 5.x et depuis Oracle 9i.
Loprateur ROLLUP GROUP BY permet de gnrer les sous-totaux de GROUP BY multi-
colonnes dans une requte unique, comme si on effectuait successivement les GROUP
BY mentionns en supprimant chaque itration le niveau de groupe le plus droite.
La requte suivante:
Select Deptno,Job, count(*) From EMP
group by rollup(Deptno, Job)
quivaut smantiquement :
Select Deptno, Job, count(*) From EMP
Group by Deptno, Job
union all
Select Deptno,null, count(*) From EMP
Group by Deptno
union all
Select null,null, count(*) From EMP
Order by 1,2
et produit le rsultat ci-aprs:
DEPTNO JOB COUNT(*)
------ --------- ----------
10 CLERK 1
10 MANAGER 1
10 PRESIDENT 1
10 3
20 CLERK 2
20 ANALYST 2
20 MANAGER 1
20 5
30 CLERK 1
30 MANAGER 1
30 SALESMAN 4
30 6
14
13 rows selected
En termes de performances, GROUP BY ROLLUP devrait tre trois fois plus rapide que
trois requtes GROUP BY successives, puisque le SGBDR ne parcourt quune fois
lensemble de donnes sources. Dans la pratique, le ratio est plutt de 2,2, ce qui est
dj bien. Ce ratio se retrouve sur le temps dexcution, le cot de loptimiseur et
les Consistent Gets.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 189
MS SQL Server
Le gain de performances est analogue celui d'Oracle.
Les versions antrieures la version2008 utilisent une notation alternative transformant
ainsi la requte:
Select Deptno,JOB, count(*) From EMP
group by Deptno,job with rollup
MySQL
MySQL supporte la notation ROLLUP. Cependant, les rsultats en performances ne sont
pas au rendez-vous, puisque la version ROLLUP est 20% plus lente que celle utilisant trois
GROUP BY. La notation est la mme que l'ancienne notation de SQL Server, il faut donc
crire ainsi:
Select Deptno,JOB, count(*) From EMP
group by Deptno,job with rollup
7.3.3 Cube Group By
Il est disponible sur SQL Server et depuis Oracle 9i.
Loprateur CUBE GROUP BY permet de gnrer les sous-totaux de toutes les dimen-
sions des GROUP BY multicolonnes dans une requte unique, comme si on effectuait
successivement les GROUP BY en faisant toutes les combinaisons possibles.
Select Deptno,JOB, count(*) From EMP
group by cube(deptno,job)
quivaut smantiquement :
Select Deptno,JOB, count(*) From EMP
Group by Deptno,JOB
union all
Select Deptno,null, count(*) From EMP
Group by Deptno
union all
Select null,job, count(*) From EMP
Group by job
union all
Select null,null, count(*) From EMP
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
190 tude et optimisation desrequtes Axe 2
et produit le rsultat ci-aprs:
DEPTNO JOB COUNT(*)
------ --------- ----------
14
CLERK 4
ANALYST 2
MANAGER 3
SALESMAN 4
PRESIDENT 1
10 3
10 CLERK 1
10 MANAGER 1
10 PRESIDENT 1
20 5
20 CLERK 2
20 ANALYST 2
20 MANAGER 1
30 6
30 CLERK 1
30 MANAGER 1
30 SALESMAN 4
18 rows selected
En termes de performances, GROUP BY CUBE devrait tre quatre fois plus rapide
que quatre requtes GROUP BY successives, puisquil ne parcourt quune seule fois
lensemble de donnes sources. Dans la pratique, le ratio est plutt de3. Ce ratio
se retrouve sur le temps dexcution, le cot de loptimiseur et les Consistent Gets.
MS SQL Server
Le gain de performance est plutt de l'ordre de 50%.
Les versions antrieures la version2008 utilisent une notation alternative transformant
ainsi la requte:
Select Deptno,JOB, count(*) From EMP
group by Deptno,job with cube
MySQL
Ne supporte pas la notation CUBE.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 191
7.3.4 Utilisation de WITH
Loprateur WITH, introduit avec Oracle 9i, permet de dclarer une sous-requte qui
va tre utilise plusieurs fois dans la requte, ce qui vite la rptition dune sous-
requte plusieurs endroits de la requte. Cela prsente un intrt en termes de
clart de code mais offre aussi lavantage damliorer parfois les performances en
favorisant la cration de tables temporaires internes.
tudions la requte suivante qui affche les informations relatives la plus grosse
ligne de commande de livres de lditeur Pearson:
select cmd.nocmd,cmd.noclient,cmd.datecommande,
cl.quantite,cl.montant,cl.nolivre
from cmd join cmd_lignes cl on cmd.nocmd=cl.nocmd
join livres l on cl.nolivre=l.nolivre
where editeur='Pearson'
and quantite=(select max(cl.quantite) quantite
from cmd_lignes cl join livres l on cl.nolivre=l.nolivre
where editeur='Pearson' )
Nous remarquons que la requte principale et la sous-requte expriment toutes les
deux une jointure entre les tables livres et cmd_lignes et fltrent sur lditeur Pear-
son. Le plan dexcution nous apprend que le SGBDR fait aussi le travail deux fois.
La requte ci-aprs est smantiquement identique mais ne rpte pas les oprations,
ni dans la requte, ni dans le plan dexcution:
with PearsonBookLignes
as (select cmd.nocmd,cmd.noclient,cmd.datecommande
,cl.quantite,cl.montant,cl.nolivre
from cmd join cmd_lignes cl on cmd.nocmd=cl.nocmd
where nolivre in (select nolivre from livres where editeur='Pearson')
)
select L.* from PearsonBookLignes L
where quantite=( select max(quantite) from PearsonBookLignes )
La version utilisant WITH est presque deux fois plus performante. Cependant, il faut
prendre garde car si la requte nomme dans la clause WITH est trop volumineuse,
la tendance peut sinverser. Dans ce cas, lutilisation du hint /*+ inline */ dans la
requte situe dans le WITH pourra tre adapte.
MS SQL Server
Cette notation est disponible depuis SQL Server 2005, mais nous n'avons pas not de
gains de performance signifcatifs.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
192 tude et optimisation desrequtes Axe 2
7.3.5 Les fonctions de classement (ranking)
Le SQL ntant pas un langage procdural, il nest pas facile dexprimer des choses
telles que le 10
e
salaire, le 50
e
employ ou le numro dordre dun classement. Dans
le pass, sous Oracle, on utilisait la pseudo-colonne Rownum et sous SQL Server et
MySQL, la clause LIMIT, mais cela sapparentait du bricolage. Les versions8.1.7
dOracle et 2005 de SQL Server ont introduit les fonctions de classement (ranking).
Elles permettent dobtenir le classement dun enregistrement dans un ensemble
quand on a spcif les critres de classement.
Par exemple, la requte ci-aprs donne pour chaque employ le rang de son salaire,
son quartile, son pourcentage dans la distribution et le numro de la ligne:
Select ename,sal,RANK() over(order by sal desc) Rang
,DENSE_RANK() over(order by sal desc) RangDense
,ROW_NUMBER() over(order by sal desc ) NoLigne
,round(PERCENT_RANK() over(order by sal desc)*100) PctRang
,NTILE(4) over(order by sal desc ) Quartile
From EMP
ENAME SAL RANG RANGDENSE NOLIGNE PCTRANG QUARTILE
------ ------ ----- ---------- -------- ------- --------
KING 5000 1 1 1 0 1
FORD 3000 2 2 2 8 1
SCOTT 3000 2 2 3 8 1
JONES 2975 4 3 4 23 1
. . . . . .
JAMES 950 13 11 13 92 4
SMITH 800 14 12 14 100 4
La diffrence entre la fonction RANK et la fonction DENSE_RANK se situe au niveau
de la gestion des enregistrements ayant le mme classement. Dans notre exemple,
SCOTT et FORD ont le mme salaire et sont tous les deux deuximes. La fonction
RANK considre quil ny a pas de troisime et JONES est donc quatrime, alors que
la fonction DENSE_RANK considre que JONES est troisime. Le classement est tabli
en suivant la clause ORDER BY mentionne dans la clause OVER( ) associe la fonc-
tion. PERCENT_RANK donne la position en pourcentage. NTILE(N) donne le N-tile de
la valeur, donc pour N=4 donne le quartile. ROW_NUMBER donne le numro de la ligne
suivant lordre spcif sans doublon.
Ces fonctions permettent aussi deffectuer des classements par partition, cest--dire
sur des sous-ensembles de donnes. Par exemple, la requte ci-aprs donne pour
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 193
chaque employ le rang de son salaire au sein de son dpartement. On constate qu
chaque changement de dpartement le classement recommence 1.
Select deptno,ename,sal,
RANK() over (PARTITION BY deptno order by sal desc) Rang
From EMP
DEPTNO ENAME SAL RANG
---------- ---------- ---------- ----------
10 KING 5000 1
10 CLARK 2450 2
10 MILLER 1300 3
20 SCOTT 3000 1
20 FORD 3000 1
20 JONES 2975 3
20 ADAMS 1100 4
20 SMITH 800 5
30 BLAKE 2850 1
. . . . . .
Les fonctions de classement permettent dcrire des requtes qui ramnent les npre-
miers enregistrements suivant un ordre (Top n). Pour cela, il sufft de mettre une
condition sur le classement. Cependant, il nest syntaxiquement pas possible de
spcifer ces fonctions dans la clause WHERE. La requte suivante provoque lerreur:
ORA-30483: fonctions de fentrage interdites ici.
Select deptno,ename,sal,RANK() over (PARTITION BY deptno order by sal desc)
Rang From EMP
where RANK() over (PARTITION BY deptno order by sal desc) =1;
Nous devons utiliser une sous-requte:
Select deptno,ename,sal
From (Select deptno,ename,sal
,RANK() over (PARTITION BY deptno order by sal desc) Rang
From EMP )
where Rang=1;
Pour obtenir le rsultat suivant:
DEPTNO ENAME SAL
------ ---------- ---------
10 KING 5000,00
20 SCOTT 3000,00
20 FORD 3000,00
30 BLAKE 2850,00
Lutilisation des fonctions de ranking pour les requtes de type Topn namliore pas
forcment les performances par rapport une solution simple avec une sous-requte
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
194 tude et optimisation desrequtes Axe 2
comme dans lexemple ci-aprs (il nest cependant pas toujours possible de trans-
former la requte de faon aussi simple):
Select deptno,ename,sal From EMP
where (deptno,sal) in (
Select deptno,max(sal)
From EMP group by deptno )
7.3.6 Autres fonctions analytiques
Les fonctions analytiques ont la capacit de travailler sur un ensemble denregistre-
ments de faon simple et souvent performante (les fonctions de classement en font
partie).
Les fonctions dagrgations classiques (MIN, MAX, SUM, AVG, COUNT) existent en ver-
sions analytiques. Dans ce mode, elles sappliquent sur une fentre glissante autour
de lenregistrement. LEAD et LAG permettent de manipuler les enregistrements prc-
dents et suivants.
Lexemple ci-aprs permet de faire des moyennes glissantes grce AVG sur une
fentre couvrant les quatre enregistrements prcdents et calcule lcart de la colonne
Sal avec les lignes suivantes et prcdentes grce aux fonctions LEAD et LAG:
SELECT ename, sal
,AVG(sal) OVER (ORDER BY sal
ROWS BETWEEN 5 PRECEDING AND 1 PRECEDING) AS MoyenneGlissante
,sal-lag(sal,1) OVER (ORDER BY sal ) AS EcartPrec
,lead(sal,1) OVER (ORDER BY sal )-sal AS EcartSuivant
FROM emp
order by sal;
ENAME SAL MOYENNEGLISSANTE ECARTPREC ECARTSUIVANT
------- ------ ---------------- ---------- ------------
SMITH 800 150
JAMES 950 800 150 150
ADAMS 1100 875 150 150
WARD 1250 950 150 0
. . . . . .
SCOTT 3000 2275 25 0
FORD 3000 2575 0 2000
KING 5000 2855 2000
Lexemple ci-aprs montre comment faire une recherche du percentile mdian de
chaque dpartement. La fonction PERCENTILE_CONT recherche le percentile de faon
continue par interpolation, alors que la fonction PERCENTILE_DISC retourne la valeur
prsente dans les donnes immdiatement infrieures ou gales la version continue.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 195
SELECT deptno ,avg(sal) as Moyenne
,PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY sal) as mediane
,PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY sal) as mediane_disc
FROM emp
group by deptno;
DEPTNO MOYENNE MEDIANE MEDIANE_DISC
------ ------- ---------- ------------
10 2916 2450 2450
20 2175 2975 2975
30 1566 1375 1250
Les fonctions REGR_xxx permettent deffectuer des rgressions linaires sur les don-
nes. (Voir la documentation de rfrence SQL dOracle.)
Concernant lutilisation de fonctions dagrgations personnalises, un besoin rcur-
rent est de pouvoir lister, dans une colonne, les enregistrements lis par une relation
matre/dtails. Cette opration tait possible dans le pass grce une fonction qui
parcourait le sous-ensemble laide dun curseur. la version9, une autre manire
plus lgante tait apparue, partir dun type et dune mthode dagrgation, mais
ctait compliqu mettre en uvre et toujours moins performant quune solution
native. La version dOracle11g Release2 rsout ce besoin en ajoutant la fonction
dagrgation native LISTAGG, qui permet de concatner des chanes de caractres
avec un sparateur dans un champ, comme illustr dans cet exemple:
select deptno,LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) as Liste
from emp group by deptno;
DEPTNO LISTE
------ --------------------------------------
10 CLARK,KING,MILLER
20 ADAMS,FORD,JONES,SCOTT,SMITH
30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD
7.3.7 L'instruction MERGE
Linstruction MERGE, introduite avec Oracle 9i, permet de fusionner une table source
dans une table destination. Tous les enregistrements de lensemble de donnes
sources prsents dans la table de destination seront mis jour et ceux qui ne sont
prsents que dans la source seront insrs. Ceux qui ne sont prsents que dans la
destination ne seront pas modifs.
Cette instruction revient faire un Update et un Insert. Elle apporte un gain de per-
formances pour les oprations de fusion de table. La syntaxe est la suivante:
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
196 tude et optimisation desrequtes Axe 2
MERGE INTO <TableDestination> USING <TableSource> on (<ClauseJointure>)
WHEN MATCHED THEN UPDATE SET <Champ>=<Expression>, .
WHEN NOT MATCHED THEN INSERT (Champ, ) values (Expression, )
MS SQL Server
L'instruction MERGE est aussi disponible. Elle peut intgrer galement le fait de supprimer
les enregistrements prsents dans la destination et pas dans la source l'aide de la clause
WHEN NOT MATCHED BY SOURCE.
MySQL
MySQL ne propose pas de solution quivalente MERGE.
7.3.8 Optimisation des updates multitables
Pour faire un update dans une table relativement des donnes contenues dans une
autre table, on crit habituellement des sous-requtes. Par exemple, la requte sui-
vante augmente les salaires des employs lists dans la table augmentation:
update bigemp e
set sal=sal+(select Montant from augmentation where empno=e.empno)
where empno in (select empno from augmentation )
Une premire solution possible pour amliorer les performances consiste utiliser
linstruction MERGE ampute de la clause WHEN NOT MATCHED. Cette solution peut
apporter un gain de performance allant jusqu 10%.
MERGE into bigemp E using augmentation A on (a.empno=e.empno)
WHEN MATCHED THEN UPDATE set sal=sal+Montant
Une autre solution, particulirement mconnue, est lutilisation dune vue dyna-
mique dans linstruction UPDATE:
update (select sal,Montant from augmentation a, bigemp e
where a.empno=e.empno)
set sal=sal+Montant
Cette solution apporte un gain trs signifcatif, puisque le temps dexcution de la
requte UPDATE passe de 33secondes 19secondes. Lexplication se trouve facile-
ment dans les plans dexcution ci-aprs. En effet, la dernire solution neffectue
quun accs la table augmentation. Les Consistent Gets passent de 2949005
12781.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 197
Figure7.2
Plan d'excution de
l'UPDATE avec sous-
requte.
Figure7.3
Plan d'excution de
l'UPDATE avec jointure.
MS SQL Server
La motivation nous poussant remplacer une instruction UPDATE par un MERGE n'existe
pas sous SQL Server, car l'instruction UPDATE est capable de faire un UPDATE en utilisant
une jointure.
MySQL
MySQL ne propose pas de solution alternative pour amliorer les updates multitables.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
198 tude et optimisation desrequtes Axe 2
7.3.9 Insertion en mode Direct Path
Le mode dinsertion Direct Path effectue les insertions dans de nouveaux blocs de
donnes, sans passer par le buffer cache. Le gain potentiel rside dans lconomie
de la recherche de place dans les blocs existants et lconomie de mmoire dans le
cache. Les inconvnients de ce mode sont nombreux aussi:
Il crit directement sur les disques. Si ces derniers sont peu performants ou occups,
la tendance peut sinverser.
Il pose un verrou sur toute la table. Ce verrou peut tre long obtenir et pnalisant
pour les autres transactions.
Un COMMIT est obligatoire immdiatement aprs une insertion.
Pour activer les insertions en mode Direct Path, il sufft dajouter le hint APPEND
linstruction INSERT. Ce hint est utilisable sur les requtes INSERT utilisant une
requte SELECT.
INSERT /*+ APPEND */ INTO ma_table SELECT * from autre_table
En PL/SQL, avec linstruction FORALL que nous tudierons la section7.4.3 de ce
chapitre, le mode Direct Path est activable laide du hint APPEND_VALUES.
7.4 PL/SQL
7.4.1 Impact des triggers
Les triggers sont des outils trs pratiques mais qui peuvent nuire trs srieusement
aux performances sur des insertions massives de donnes. Il faudra particulirement
veiller leffcacit du code contenu dans les triggers des tables trs mouvementes.
Mme si le code du trigger est optimal, lappel mme du trigger un cot. Nous
illustrons ce phnomne en transfrant le contenu de la table client (45000enre-
gistrements) dans la table clients2 en convertissant le champ Nom en majuscules,
soit en appelant la fonction UPPER() dans une requte SQL, soit avec un trigger qui
effectue cette opration.
Listing7.1: Premire solution, compltement en SQL
insert into clients2
select noclient, upper(nom), prenom, adresse1, adresse2, codepostal, ville,
pays, tel, email from clients
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 199
Listing7.2: Deuxime solution, utilisant un trigger PL/SQL
create or replace trigger TRG_BEFORE_INS_CLIENTS2
before insert on clients2 for each row
begin
:new.nom:=upper(:new.nom);
end;
/
insert into clients2
select noclient, nom, prenom, adresse1, adresse2, codepostal, ville, pays,
tel, email from clients
Le rsultat est sans appel : la premire solution sexcute en 94 ms, alors que la
deuxime, avec le trigger, sexcute en 485ms. Lcart de temps correspond princi-
palement linvocation du trigger PL/SQL.
Il faut essayer de rduire les excutions des triggers et, pour cela, la clause mconnue
WHEN peut tre utile. Elle permet dvaluer une condition afn de dcider dexcuter
le trigger ou pas. Dans le cadre de notre exemple, il est inutile dexcuter le trigger
si la donne est dj en majuscules, nous pouvons donc mettre cela en condition
pralable dans la clause WHEN.
Listing7.3: Troisime solution, utilisant un trigger PL/SQL avec une clause WHEN
CREATE OR REPLACE TRIGGER TRG_BEFORE_INS_CLIENTS2
before insert on clients2 for each row
when (new.nom!=upper(new.nom))
begin
:new.nom:=upper(:new.nom);
end;
/
insert into clients2
select noclient, upper(nom), prenom, adresse1, adresse2, codepostal, ville,
pays, tel, email from clients
Nous constatons que si les donnes en entre sont dj en majuscules, le gain est trs
signifcatif, puisque le temps dexcution passe 109ms, soit un surcot de 15ms.
Ce gain provient du fait quil ny a pas invoquer le moteur PL/SQL pour tester
la clause WHEN. Si les donnes ne sont pas en majuscules, le surcot est l aussi de
15ms (on passe de 485ms 500ms).
Une autre solution pour viter lexcution inutile de trigger se trouve au niveau de la
clause OF sur les triggers UPDATE. Cette clause permet de nexcuter le trigger que
si les colonnes quelle spcife sont prsentes dans la requte UPDATE. Lutilisation
de cette clause avec un trigger en UPDATE qui effectue le mme travail que le trigger
INSERT est illustre ci-aprs.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
200 tude et optimisation desrequtes Axe 2
Listing7.4: Trigger utilisant une clause UPDATE OF
CREATE OR REPLACE TRIGGER TRG_BEFORE_UPD_CLIENTS2
before update OF nom on clients2 for each row
begin
:new.nom:=upper(:new.nom);
end;
/
update clients2 set prenom=prenom;
Lexcution de la requte UPDATE ne concernant pas la colonne Nom prend 469ms
avec la clause OF alors quelle prend sinon 1125ms cause de lexcution inutile du
trigger et de la rcriture inutile de la valeur du champ Nom quelle ncessite.
7.4.2 Optimisation des curseurs (BULK COLLECT)
La manire classique en PL/SQL consiste utiliser des curseurs dans des boucles
FOR qui permettent de rcuprer les lignes une par une. Cela fonctionne bien mais ce
nest pas trs performant lorsque le volume des enregistrements devient important
car il ny a quun enregistrement rcupr (fetch) par itration. Afn damliorer les
performances de la rcupration des enregistrements, nous avons notre disposition
les instructions BULK COLLECT utilisables dans les instructions suivantes :
Select .. Into
Fetch .. Into
Returning .. Into
La rcupration seffectue alors par blocs dans des tableaux et non pas dans des
variables scalaires. Il sufft juste de faire prcder le mot cl INTO par BULK COLLECT.
Illustrons sa mise en uvre par le remplacement dun curseur sur un programme
simple qui calcule la somme des salaires:
Listing7.5: Version en PL/SQL classique
declare
Cursor c1 is select sal from bigemp;
somme number;
begin
somme:=0;
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 201
for rec in C1 loop
somme:=somme+rec.sal;
end loop;
dbms_output.put_line(somme);
end;
Temps dexcution: 1,26s
Listing7.6: Version en PL/SQL utilisant SELECT BULK COLLECT INTO
declare
somme number;
TYPE Table_N IS table OF Number ;
lstsal Table_N;
begin
somme:=0;
SELECT sal BULK COLLECT INTO lstsal FROM bigemp;
for j in lstsal.rst..lstsal.last loop
somme:=somme+lstsal(j);
end loop;
dbms_output.put_line(somme);
end;
Temps dexcution: 0,51s (On constate un gain de performances signifcatif.)
On constate que la solution utilisant linstruction BULK COLLECT dissocie la rcup-
ration des donnes de leur traitement en les stockant dans un tableau. Cette solution,
en plus du gain de performances, offre si ncessaire plus de fexibilit au niveau
du parcours des donnes issues de la requte. Le fait de stocker le rsultat dans un
tableau ne contraint pas davoir un parcours unidirectionnel comme limpose un
curseur classique.
Cependant, comme rien nest jamais magique, cette seconde solution consomme
plus de ressource mmoire. Il se peut que cette solution pose des problmes lis
une saturation de la mmoire si le volume des donnes est trop important. Si cest le
cas, vous pouvez utiliser un curseur BULK COLLECT.
Il sagit dun curseur qui rcupre non pas un seul enregistrement par fetch mais un
ensemble denregistrements qui sont mis dans un tableau dont la taille est spcife
laide de la clause LIMIT. Cette technique est une solution intermdiaire entre le
curseur classique et le SELECT INTO BULK COLLECT, qui permet de rcuprer les
donnes par paquets de taille intermdiaire. Cette solution ncessite gnralement
lutilisation de deux boucles imbriques (voir Listing7.7).
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
202 tude et optimisation desrequtes Axe 2
Listing7.7: Version en PL/SQL utilisant FETCH BULK COLLECT INTO
declare
Cursor c1 is select sal from bigemp e;
somme number;
TYPE Table_N IS table OF Number ;
lstsal Table_N;
begin
somme:=0;
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO lstsal LIMIT 1000;
EXIT WHEN c1%NOTFOUND;
for j in lstsal.rst..lstsal.last loop
somme:=somme+lstsal(j);
end loop;
end loop;
dbms_output.put_line(somme);
end;
Le temps dexcution de cette version est de 0,64seconde. Cest toujours en progrs
signifcatif par rapport un curseur conventionnel mais en recul par rapport la
solution SELECT INTO BULK COLLECT. Cela sexplique par le fait que la requte ne
pose pas de problme de volume, le cot des oprations supplmentaires impliques
par cette solution nest compens par aucun gain.
Afn de mettre en vidence dventuels problmes de performances lis aux volumes,
nous allons faire quelques tests en faisant fuctuer la clause LIMIT sur une variante
qui ramne les enregistrements complets au lieu de ne ramener que la colonne Sal.
Listing7.8: Version en PL/SQL utilisant FETCH BULK COLLECT ramenant les enregistrements
entiers
declare
Cursor c1 is select e.* from bigemp e;
somme number;
TYPE Table_N IS table OF c1%rowtype ;
lstsal Table_N;
begin
somme:=0;
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO lstsal LIMIT 100;
EXIT WHEN c1%NOTFOUND;
for j in lstsal.rst..lstsal.last loop
somme:=somme+lstsal(j).sal;
end loop;
end loop;
dbms_output.put_line(somme);
end;
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 203
Tableau7.1: Analyse des performances en fonction de la clause LIMIT
Clause LIMIT Temps d'excution
1 19,5s
10 4,5s
100 3,25s
1 000 2,59s
10 000 2,59s
100 000 3,11s
500 000 3,27s
1 000 000 3,70s
Nous constatons que la rcupration (fetch) par blocs de quelques milliers denre-
gistrements est optimale pour ce cas-l. La valeur 1000 est une valeur adapte pas
mal de cas, elle permet de rduire par 1000 le nombre de fetches tout en utilisant
une quantit de mmoire raisonnable pour le tableau. Si vous navez pas le temps
de faire une valuation plus approfondie, cest une valeur assez polyvalente qui
convient dans la plupart des cas.
7.4.3 Optimisation du LMD (FORALL)
La modifcation de donnes partir de curseurs (classique ou BULK COLLECT) a pour
effet de multiplier le nombre dexcutions dinstructions de type LMD (INSERT,
UPDATE, DELETE). Cette mthode peut avoir un impact signifcativement ngatif sur
les performances par rapport du SQL classique.
Afn damliorer les performances de ce type dopration, il existe un quivalent au
BULK COLLECT pour le LMD au travers de linstruction FORALL qui a la syntaxe
suivante:
FORALL index IN lower_bound..upper_bound
Instruction_SQL_LMD;
FORALL permet de manipuler des instructions du LMD avec des tableaux, ce qui
rduit le nombre dexcutions de requtes. Chaque FORALL nexcutera linstruction
quune seule fois avec des tableaux comme paramtres au lieu de valeurs scalaires.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
204 tude et optimisation desrequtes Axe 2
Listing7.9: Exemple d'utilisation de FORALL
DECLARE
TYPE Table_N IS table OF Number ;
lstempno Table_N ;
lstmontant Table_N ;
begin
SELECT empno, aug BULK COLLECT INTO lstempno,lstmontant FROM empbigaug;
forall j in lstempno.rst..lstempno.last
UPDATE empbig set SAL=SAL+lstmontant(j) where empno=lstempno(j);
end;
Nous allons valuer les performances de cette solution travers un petit programme
qui augmente les salaires de la localisation "DALLAS" de 10 et ceux de la localisa-
tion "Toulouse" de 31. Le programme est quivalent aux instructions SQL suivantes
que nous utilisons comme rfrence:
Listing7.10: Version SQL UPDATE
update bigemp e
set sal=sal+(select decode(loc,'CHICAGO',10,'Toulouse',31,0)
from bigdept where deptno=e.deptno)
where deptno in (select deptno from bigdept
where loc in ('CHICAGO','Toulouse') );
Temps dexcution: 11,32 s
Listing7.11: Version SQL MERGE
merge into bigemp e using
(select empno,sal+decode(loc,'CHICAGO',10,'Toulouse',31,0) NewSal
from bigemp e,bigdept d
where e.deptno=d.deptno and loc in ('CHICAGO','Toulouse')) A
on (E.empno=A.empno)
when matched then update Set sal=Newsal;
Temps dexcution: 12,81s
Listing7.12: Version SQL UPDATE optimis avec jointure
update (SELECT sal ,DECODE (loc, 'CHICAGO', 10, 'Toulouse', 31, 0) bonus
FROM bigdept,bigemp
WHERE bigdept.deptno = bigemp.deptno
and loc IN ('CHICAGO', 'Toulouse') )
set sal=sal+bonus;
Temps dexcution: 9,21s
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 205
Listing7.13: Version PL/SQL de base
declare
Cursor c1 is select empno,sal,loc from bigemp e,bigdept d
where e.deptno=d.deptno for update of e.sal;
begin
for rec in C1 loop
if rec.loc in ('CHICAGO','Toulouse') then
update bigemp
set sal=sal+decode(rec.loc,'CHICAGO',10,'Toulouse',31,0)
where current of c1;
end if;
end loop;
end;
Temps dexcution: 66,07s
Cette version effectue le fltrage des lignes dans le PL/SQL et ramne des lignes inu-
tilement. Le fltrage des enregistrements dans un bloc PL/SQL au lieu dune clause
WHERE est gnralement bannir.
Listing7.14: Version PL/SQL de base avec une clause WHERE dans le curseur
declare
Cursor c1 is select empno,sal,loc from bigemp e,bigdept d
where e.deptno=d.deptno and loc in ('CHICAGO','Toulouse')
for update of e.sal;
begin
for rec in C1 loop
update bigemp
set sal=sal+decode(rec.loc,'CHICAGO',10,'Toulouse',31,0) *
where current of c1;
end loop;
end;
Temps dexcution: 28,51s
Nous voyons que, gnralement, les instructions SQL simples sont plus perfor-
mantes que l'quivalent en PL/SQL.
Listing7.15: Version utilisant un curseur BULK COLLECT
declare
Cursor c1 is select empno,sal,loc,e.rowid from bigemp e,bigdept d
where e.deptno=d.deptno and loc in ('CHICAGO','Toulouse');
TYPE C1RecTab IS TABLE OF c1%rowtype;
Recs C1RecTab;
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
206 tude et optimisation desrequtes Axe 2
begin
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO Recs LIMIT 1000;
EXIT WHEN c1%NOTFOUND;
for j in Recs.rst..Recs.last loop
update bigemp
set sal=sal+decode(recs(j).loc,'CHICAGO',10,'Toulouse',31,0)
where rowid=recs(j).rowid;
end loop;
END LOOP;
CLOSE c1;
end;
Temps dexcution: 20,8s
On remarque lutilisation du RowID permettant dimplmenter lquivalent de la
clause CURRENT OF de la version prcdente.
Listing7.16: Version utilisant un curseur BULK COLLECT et un FORALL avec clause WHERE
sur le champ Empno
declare
Cursor c1 is select empno,sal,loc from bigemp e,bigdept d
where e.deptno=d.deptno and loc in ('CHICAGO','Toulouse');
TYPE C1RecTab IS TABLE OF c1%rowtype;
Recs C1RecTab;
TYPE Table_N IS table OF Number ;
lstempno Table_N:=Table_N();
lstnewsalary Table_N:=Table_N() ;
TblIidx integer;
begin
lstempno.extend(1000);lstnewsalary.extend(1000);
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO Recs LIMIT 1000;
EXIT WHEN c1%NOTFOUND;
TblIidx:=1;
for j in Recs.rst..Recs.last loop
lstempno(TblIidx):=Recs(j).empno;
if recs(j).loc = 'CHICAGO' then
lstnewsalary(TblIidx):=Recs(j).sal+10;
else
lstnewsalary(TblIidx):=Recs(j).sal+31;
end if;
TblIidx:=TblIidx+1;
end loop;
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 207
forall j in 1..(TblIidx-1)
update bigemp set sal=lstnewsalary(j) where empno=lstempno(j);
END LOOP;
CLOSE c1;
end;
Temps dexcution: 11,3s
On remarque un gain de performances assez important avec lintroduction de FORALL.
Cependant, si nous regardons le schma dexcution de linstruction UPDATE, nous
voyons que lindex PK_BIGEMP est en toute logique mis contribution alors que
lhabituelle clause CURRENT OF travaille directement sur les RowID. La version
suivante montre le gain apport par le travail direct avec les RowID.
Listing7.17: Version utilisant un curseur BULK COLLECT et un FORALL avec clause WHERE
sur le RowID
declare
Cursor c1 is select sal,loc,e.rowid from bigemp e,bigdept d
where e.deptno=d.deptno and loc in ('CHICAGO','Toulouse');
TYPE C1RecTab IS TABLE OF c1%rowtype;
Recs C1RecTab;
TYPE Table_N IS table OF Number ;
TYPE Table_RowId IS table OF Rowid ;
lstnewsalary Table_N:=Table_N() ;
lstrowid Table_RowId:=Table_RowId() ;
SampleSize integer := 1000;
TblIidx integer;
begin
lstnewsalary.extend(SampleSize);lstrowid.extend(SampleSize);
OPEN c1;
LOOP
FETCH c1 BULK COLLECT INTO Recs LIMIT SampleSize;
EXIT WHEN c1%NOTFOUND;
TblIidx:=1;
for j in Recs.rst..Recs.last loop
if recs(j).loc = 'CHICAGO' then
lstnewsalary(TblIidx):=Recs(j).sal+10;
else
lstnewsalary(TblIidx):=Recs(j).sal+31;
end if;
lstrowid(TblIidx):=Recs(j).rowid;
TblIidx:=TblIidx+1;
end loop;
forall j in 1..(TblIidx-1)
update bigemp set sal=lstnewsalary(j) where rowid=lstrowid(j);
END LOOP;
CLOSE c1;
end ;
Temps dexcution: 9,57s
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
208 tude et optimisation desrequtes Axe 2
Tableau7.2: Rsum des versions et des temps d'excution associs
Mthode
Temps d'excution
(en secondes)
SQL UPDATE 11,32
SQL MERGE 12,81
SQL UPDATE optimis 9,21
PL/SQL curseur de base sans WHERE 66,07
PL/SQL curseur de base avec WHERE 28,51
PL/SQL select BULK COLLECT 20,80
PL/SQL select BULK COLLECT plus FORALL sur Empno 11,30
PL/SQL select BULK COLLECT plus FORALL sur RowID 9,57
Nous constatons une certaine diversit dans les performances, mais lintroduction
des techniques BULK COLLECT et FORALL a un effet indniable. On arrive mme avoir
des performances proches du SQL optimis en PL/SQL, ce qui nest pas frquent
tant donn la nature mme du PL/SQL qui sappuie sur le SQL.
INFO
Ces techniques, dites BULK, sont aussi prsentes sur certaines API clientes telles que les pr-
compilateurs (Pro*C,etc.).
7.4.4 SQL dynamique et BULK
Les mthodes de SQL dynamiques peuvent aussi utiliser les fonctionnalits BULK au
moyen des notations suivantes:
FORALL i IN <Intervale>
EXECUTE IMMEDIATE '<Instruction LMD avec des bindings>'
USING <tableau>(i);
Vous pouvez mme y insrer une clause RETURNING :
FORALL i IN tabdept.rst .. tabdept.last
'DELETE FROM bigemp WHERE DeptNo = :1
RETURNING Empno INTO :2'
USING tabdept(i) RETURNING BULK COLLECT INTO tabempno;
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 7 Techniques d'optimisation desrequtes avances 209
Dans le cas de curseurs dynamiques, vous pouvez utiliser la syntaxe suivante:
OPEN c FOR <variable contenant un select>;
FETCH c BULK COLLECT INTO <tableau>;
CLOSE c;
Dans le cas dun SELECT INTO dynamique de type BULK COLLECT, vous pouvez
utiliser:
EXECUTE IMMEDIATE <variable contenant un select>
BULK COLLECT INTO <tableau>;
7.4.5 Traitement des exceptions avec FORALL
Il est possible que, lors de lexcution dinstructions LMD, des exceptions soient
leves car des contraintes ne sont pas respectes. Le rsultat avec FORALL sera le
mme que si on avait utilis un curseur: les lignes qui prcdent lexception sont
modifes mais pas celles qui suivent la ligne lorigine de lexception. Ce com-
portement est parfois acceptable, surtout si vous prvoyez de faire un ROLLBACK.
Par contre, si votre objectif est de conserver tout ce qui peut se faire et de tracer
ce qui pose problme, la solution standard qui interrompt le traitement nest pas la
bonne.
Oracle met notre disposition le mot cl SAVE EXCEPTIONS dans linstruction FORALL.
Il a pour effet de stocker les exceptions dans un tableau et de lever lexception
"ORA24381: Error in Array DML". Cela conduit la situation suivante:
Les exceptions sont disponibles dans le tableau SQL%BULK_EXCEPTIONS.
Le nombre dexceptions est accessible par SQL%BULK_EXCEPTIONS.count.
La ligne du tableau origine de lexception est dans
SQL%BULK_EXCEPTIONS(i).error_index.
Le code de lexception est dans SQL%BULK_EXCEPTIONS(i).Error_code.
Pour traiter les exceptions, il faut capturer lexception ORA-24381 et parcourir le
tableau SQL%BULK_EXCEPTIONS.
Pour capturer une exception, il faut dabord la dclarer dans la section DECLARE au
moyen des instructions suivantes:
ex_erreur_dml EXCEPTION;
PRAGMA EXCEPTION_INIT(ex_erreur_dml, -24381);
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Listing7.18: Exemple de traitement des exceptions
BEGIN
forall j in 1..(TblIidx-1) SAVE EXCEPTIONS
update bigemp set sal=lstnewsalary(j) where rowid=lstrowid(j);
EXCEPTION
WHEN ex_erreur_dml THEN
NbrErreur := SQL%BULK_EXCEPTIONS.count;
DBMS_OUTPUT.put_line(NbrErreur ||' erreurs');
FOR i IN 1 .. NbrErreur LOOP
DBMS_OUTPUT.put_line('Erreur: ' || i ||
' Index tableau : ' || SQL%BULK_EXCEPTIONS(i).error_index ||
' Message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
END LOOP;
END;
7.4.6 Utilisation de cache de donnes
Si une procdure comme celles qui utilisent des tables de rfrences risque de rechercher
de nombreuses fois les mmes donnes dans les tables, il peut tre pertinent dutiliser les tech-
niques de cache, en stockant une copie de la table ou les donnes rcemment utilises dans une
variable tableau de type TABLE.
Illustrons cette technique avec le programme ci-aprs qui compte le nombre de commandes
de clients situs en France en PL/SQL, volontairement sans utiliser de jointure des fns de
dmonstration.
Listing7.19: Version de base
declare
NbrCmd Number :=0;
Pays varchar(15);
begin
for c in (select * from cmd where rownum<100000)
loop
select pays into Pays from clients where noclient=c.noclient;
if Pays='France' then
NbrCmd:=NbrCmd+1;
end if;
end loop;
dbms_output.put_line('Nbr Cmd = '||NbrCmd);
end;
Listing7.20: Version utilisant une variable de cache
declare
NbrCmd Number :=0;
Pays varchar(15);
TYPE Table_A15 IS table OF varchar(15) index by BINARY_INTEGER;
CacheClient Table_A15;
begin
for c in (select * from cmd where rownum<100000)
loop
if CacheClient.exists(c.noclient) then
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Pays:=CacheClient(c.noclient);
else
select pays into Pays from clients where noclient=c.noclient;
CacheClient(c.noclient):=Pays;
end if;
if Pays='France' then
NbrCmd:=NbrCmd+1;
end if;
end loop;
dbms_output.put_line('Nbr Cmd = '||NbrCmd);
end;
On peut mme imaginer donner au cache une dure de vie suprieure la procdure en cours,
en utilisant des variables de package qui ont pour dure de vie la dure de la session. Dans ce
cas, il faut particulirement veiller au problme de validit du cache, car ses donnes risquent
de devenir obsoltes. Cette technique peut avoir pour effet doccuper beaucoup de mmoire,
car chaque association de valeurs va rester en mmoire et, cela, pour chaque excution de la
fonction ou pour chaque session si une variable de package est utilise.
Oracle 11g apporte une solution complmentaire avec le cache de rsultat de fonction. Elle
permet de mmoriser en cache le rsultat dune fonction de faon partage entre les sessions et
en limitant les ressources utilises grce un algorithme de type LRU (Least Recently Used).
Cette fonctionnalit permet aussi de grer linvalidation des donnes en cache la suite de
modifcations de table laide de la clause RELIES_ON. Celle-ci est optionnelle et Oracle semble
pouvoir sen passer lors de lanalyse du code. Les paramtres de la base RESULT_CACHE_MAX_
SIZE et RESULT_CACHE_MAX_RESULT permettent de grer la mmoire disponible pour le cache de
chaque fonction. Par dfaut, chaque fonction peut utiliser au plus 5% de la mmoire de cache
de rsultat (RESULT_CACHE_MAX_SIZE) qui est fx quelques pourcents de la taille de la SGA.
Si vous prvoyez dutiliser intensment cette fonctionnalit, il faudra probablement ajuster les
valeurs de ses paramtres.
Listing7.21: Version utilisant une fonction avec l'option RESULT_CACHE
create or replace function GetPaysClient(pNoClient number) return varchar2
RESULT_CACHE relies_on (clients) is
Pays varchar2(15);
begin
select pays into Pays from clients where noclient=pnoclient;
return(Pays);
end GetPaysClient;
/
declare
NbrCmd Number :=0;
begin
for c in (select * from cmd where rownum<100000 order by noclient)
loop
if GetPaysClient(c.noclient)='France' then
NbrCmd:=NbrCmd+1;
end if;
end loop;
dbms_output.put_line('Nbr Cmd = '||NbrCmd);
end;
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
7.4.7 Utilisation du profling
Le package DBMS_PROFILER permet de tracer lexcution de code PL/SQL et ainsi de connatre,
pour chaque ligne de code, le nombre dexcutions et le temps total dexcution. Cette fonc-
tion permet de dtecter les points critiques pour amliorer les performances dune procdure.
DBMS_PROFILER stocke les rsultats dans une table interrogeable via SQL. Lidal est duti-
liser des outils tiers intgrant le profling qui mettent disposition des rapports comme celui
de la Figure7.4.
Figure7.4
Rapport de profling issu de l'outil PL/SQL Developer d'Allround Automations.
7.4.8 Compilation du code PL/SQL
Depuis de nombreuses versions dOracle, il est possible de compiler le code des procdures
stockes que vous dveloppez ainsi que celles qui sont livres en standard. Cependant,
cette procdure tait assez complexe jusqu la version 11g qui a normment simplif
les choses.
De faon standard, le code PL/SQL est interprt par un runtime du noyau, mais il est possible
de le compiler afn davoir du code natif la plateforme. Cette opration, si elle napporte pas
forcment des gains signifcatifs, ne peut pas rduire les performances de faon signifcative.
Il convient cependant de ne compiler que ce qui doit ltre. Tout le code excutant du SQL ne
subira aucune amlioration. Si votre procdure excute principalement du SQL, il ny a pas
dintrt la compiler.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Pour compiler en code natif partir dOracle11g, il sufft de recompiler la procdure en sp-
cifant le type de code NATIVE.
ALTER PROCEDURE <nomProcedure> COMPILE PLSQL_CODE_TYPE=NATIVE ;
Il faut bien veiller ne pas laisser les informations de dbogage (clause DEBUG) pour tirer parti
des gains de performances. Le code compil ne peut pas tre profl ou dbogu. Ltape de
compilation native ne devra donc avoir lieu quaprs la mise au point du code.
Listing7.22: Exemple de procdure effectuant des oprations non SQL et pouvant tirer pleinement
proft de la compilation (tri bulle d'une table dcroissante)
create or replace procedure TestPerf is
TYPE Table_N IS table OF pls_INTEGER INDEX BY pls_INTEGER;
Tbl Table_N ;
Taille pls_INTEGER :=4000;
modied boolean;
swap integer;
begin
-- On rempli le tableau tri en dcroissant
for j in 1..taille
loop
Tbl(j):=taille-j;
end loop;
-- On tri le tableau
loop
modied:=false;
for j in 1..taille-1
loop
if Tbl(j)>Tbl(j+1) then
swap:=Tbl(j);
Tbl(j):=Tbl(j+1);
Tbl(j+1):=swap;
modied:=true;
end if;
end loop;
exit when not modied;
end loop;
end TestPerf;
Cette procdure en code interprt sexcute en 4,8secondes. Aprs la compilation native, elle
le fait en 1,9seconde, ce qui constitue un gain notable.
La requte suivante permet de connatre le type de code et la prsence dinformations de dbo-
gage de tout le code PL/SQL de lutilisateur.
SELECT * FROM user_PLSQL_OBJECT_SETTINGS
ORDER BY TYPE, PLSQL_CODE_TYPE;
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Axe 3
Autres pistes doptimisation
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
8
Optimisation applicative
(hors SQL)
En gnral, une application nest pas seulement une base de donnes, mais un appli-
catif qui utilise une base de donnes. Ct applicatif, certains choix peuvent avoir
de grosses rpercussions sur linteraction avec la base de donnes. Nous resterons
au fl de ce chapitre assez gnraliste, car les techniques sont propres chaque
environnement de dveloppement.
8.1 Impact du rseau sur le modle client/serveur
Si le rseau est peu performant et que lapplication soit de type client lourd, on
veillera rduire le nombre de requtes excutes sur le serveur, nombre qui peut
rapidement exploser avec des relations matre/dtails.
On veillera ne pas ramener des ensembles de donnes entiers sil est possible de
les ramener petit petit. Un maximum de fltrages et de regroupements seront faits
ct SGBDR afn de limiter les volumes transfrs sur le rseau.
8.2 Regroupement de certaines requtes
Loverhead de lexcution dune requte se dfnit par le temps ncessaire son
excution qui nest pas consacr au parcours des donnes cela inclut les changes
interprocessus et rseaux, lanalyse,etc. Il est gnralement considr comme faible.
Cependant, ce temps peut devenir trs signifcatif par rapport au temps total sur des
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
218 Autres pistes doptimisation Axe 3
requtes simples. Si beaucoup de requtes sont excutes, des problmes de latence
peuvent surgir. Lapparition dORM (Object-Relational Mapping) et de framework
a contribu mettre ce problme en exergue.
Illustrons ce phnomne avec un exemple: imaginons que, dans notre base exemple,
nous souhaitions rcuprer les informations relatives un client qui a pass 10com-
mandes de 5articles pris dans notre catalogue de livres.
Une solution que pourrait apporter un ORM gnrant des requtes SQL peu perfor-
mantes se dcomposerait ainsi:
1requte pour rcuprer le client;
1requte pour rcuprer la collection de 10commandes;
10requtes pour rcuprer les 5articles de chacune des commandes;
50requtes pour rcuprer les 50articles commands (sils sont tous diffrents).
Soit 62requtes SQL.
Une autre approche, parfois plus effcace, serait:
1requte pour rcuprer le client;
1requte pour rcuprer les commandes;
1requte pour rcuprer les items de commandes joints avec les articles.
Soit 3requtes SQL.
Comme souvent lorsquon parle doptimisation, la notion de performance dpend
de pas mal de choses. Si lORM utilise des mcanismes de lazy loading, qui per-
met dattendre le premier accs effectif une donne, il nexcutera pas forcment
toutes les requtes. Si lapplication a la capacit de maintenir un cache des objets,
les articles resteront en mmoire et ne seront pas extraire chaque fois.
Le regroupement de requtes peut conduire dupliquer des donnes et donc gas-
piller des ressources. Par exemple, si les mmes articles sont prsents dans plusieurs
commandes, la seconde solution va, inutilement, les ramener plusieurs fois.
Certaines personnes pensent, tort, que lutilisation dun ORM vite davoir se
plonger dans la base de donnes et que tout marchera tout seul. Les ORM nont
rien de magique. Leurs atouts sont indniables dans certains environnements, plus
discutables dans dautres. Il est impratif de se pencher sur la confguration des ORM
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 8 Optimisation applicative (hors SQL) 219
pour ne pas tomber dans des travers tels que celui dcrit prcdemment. Les ORM
peuvent tout fait gnrer du SQL performant sils sont correctement confgurs.
Hibernate, par ailleurs, intgre un langage HQL qui permet de faire des requtes
performantes dans le SGBDR au lieu de parcourir des collections dobjets quil
faudrait pralablement rcuprer.
Le problme de la multiplication des requtes arrive aussi dans dautres circons-
tances. Jai eu plusieurs fois loccasion de voir dans des applications des boucles
dans lapplicatif l o une jointure aurait t pertinente. Ci-aprs fgure un exemple
de code multipliant les requtes inutilement:
$ListeCmd=$db->GetArray("select * from cmd where noclient=$noclient");
foreach($ListeCmd as $cmd)
{
$LignesCommandes=$db->GetArray("select * from lignes_cmd where
nocmd=".$cmd['nocmd']);
// Traitement
}
8.3 Utilisation du binding
Le binding est un mcanisme qui permet dexcuter plusieurs fois la mme requte
en changeant la valeur des paramtres. Sous Oracle, cette technique utilise des
paramtres prfxs par le symbole deux points (:). La valeur effective est passe
sparment du texte de la requte. Exemple dune requte utilisant un binding sous
Oracle:
Select * from clients where Noclient=:P1
Cette technique permet dconomiser le temps danalyse de la requte sur les ex-
cutions suivant la premire, ce qui peut tre intressant si une mme requte est
utilise de nombreuses fois.
Lexemple ci-aprs en PHP montre deux solutions possibles:
La premire modife le texte de la requte et la re-parse donc chaque fois.
La seconde utilise un binding.
Le rsultat est sans appel: on passe de 7,68secondes 1,05seconde soit un fac-
teur7 pour 10000excutions. Sur 1000excutions, le facteur nest plus que de 2,5,
ce qui est dj un bon rsultat. Bien videmment, le facteur de gain dpend de la
requte excute.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
220 Autres pistes doptimisation Axe 3
Listing8.1: Comparaison de requtes avec et sans binding
<?php
$conn = oci_connect('scott', 'tiger', 'orcl');
// Version sans binding
$start= microtime (true);
for($i=0;$i<10000;$i++)
{
$query = 'SELECT * FROM clients where noclient='.(14797+$i);
$stid = oci_parse($conn, $query);
$r = oci_execute($stid, OCI_DEFAULT);
$row = oci_fetch_row($stid);
oci_free_statement ($stid);
}
echo microtime (true)-$start;
// Version Avec binding
$start= microtime (true);
$query = 'SELECT * FROM clients where noclient=:client';
$stid = oci_parse($conn, $query);
for($i=0;$i<10000;$i++)
{
$client=14797+$i;
oci_bind_by_name ( $stid , 'client', $client );
$r = oci_execute($stid, OCI_DEFAULT);
$row = oci_fetch_row($stid);
}
oci_free_statement ($stid);
echo microtime (true)-$start;
oci_close($conn);
?>
Dans le cadre de lutilisation de paramtres binds sur des prdicats dintervalles
dans une instruction SELECT, les bindings peuvent fausser les estimations car lopti-
miseur recourt des valeurs prdfnies telles que 5% pour les intervalles ouverts
(>x) et 0,25% pour les intervalles borns (>x AND <y) [voir Chapitre5, section5.1.3,
"Slectivit, cardinalit, densit"].
Ces estimations pouvant poser des problmes, la version10g a introduit la notion
de Bind Peeking qui a pour effet de dterminer le cot en fonction de la premire
valeur utilise. Cette solution donne parfois de meilleurs rsultats mais elle a pro-
voqu une leve de boucliers dans la communaut car elle entranait des instabilits
du plan dexcution utilis pour une mme requte en fonction de la premire valeur
soumise, ce qui avait un aspect alatoire.
La version 11g a chang de mthode en introduisant les Adaptive Cursors. Cette
technique permet de grer plusieurs plans dexcution pour une mme requte uti-
lisant le binding, loptimiseur choisissant ensuite le plan le plus adapt la valeur
soumise.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 8 Optimisation applicative (hors SQL) 221
8.4 Utilisation de cache local l'application
Plutt que de rinterroger la base de donnes chaque fois quon a besoin dune donne
de rfrence, il peut tre plus performant dutiliser un cache local. Comme avec tous
les caches, cette solution introduit le problme de la dure de validit des donnes
du cache et des ventuels comportements inadquats que cela peut entraner.
8.5 Utilisation du SQL procdural
Parfois, la logique mtier exige invitablement de faire un grand nombre de requtes.
Plutt que de coder toute la logique du ct client de lapplication, il peut tre per-
tinent de la coder avec du SQL procdural (bloc PL/SQL sous Oracle, Transact
SQL sous SQL Server). Lavantage de cette solution est que les procdures seront
excutes dun seul coup sans quitter le noyau, ce qui rduit loverhead de chaque
requte. Les performances sont gnralement au rendez-vous sil y a de nombreuses
requtes.
Au-del des aspects relatifs aux performances, le SQL procdural est parfois utilis
pour implmenter la sparation dun applicatif en plusieurs couches. Dans ce cas,
la logique mtier est implmente laide de procdures stockes et de packages.
8.6 Gare aux excs de modularit
Parfois, vouloir trop bien faire, on peut introduire des problmes de performances.
Par exemple, dans un souhait de dcouplage de deux applications, vous dcidez
de mettre disposition dans une des applications un package PL/SQL permettant
de manipuler et dinterroger les donnes. Supposons que ce package contienne les
fonctions suivantes:
GetCmdClient(NoClient). Retourne les commandes dun client.
GetMontantCmd (NoCmd). Retourne le montant dune commande.
Ces fonctions sont adaptes aux oprations pour lesquelles elles ont t dfnies.
Cependant, il se peut que les besoins voluent et que linterface ne suive pas. Par
exemple, si vous avez besoin de calculer le chiffre daffaires dun client, vous allez
appeler GetCmdClient puis GetMontantCmd pour chaque commande. Cette approche
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
222 Autres pistes doptimisation Axe 3
sera moins effcace que de faire une requte SQL calculant directement ce chiffre
daffaires.
De faon gnrale, la manipulation des bases de donnes se prte relativement peu
la prsentation dAPI pour agir sur les donnes sous-jacentes. Considrez donc les
impacts si vous devez recourir ce genre de mcanisme. Lutilisation de vues (avec
les rserves prsentes au Chapitre6, section6.2.4, "Rutilisation de vue") peut tre
une solution plus performante que des procdures PL/SQL.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
9
Optimisation de linfrastructure
9.1 Optimisation de l'excution du SGBDR
Cette tche est plutt dans le primtre de ladministrateur de la base de donnes,
mais nous abordons ici quelques pistes de base. Des dizaines de paramtres sont
disponibles pour adapter le comportement des SGBDR. Il faut les manipuler avec
beaucoup de prudence car ils peuvent avoir de lourdes consquences seul, un DBA
devrait normalement les modifer. Si vous navez pas de DBA, les modules AWR et
ADDM tudis au Chapitre4, section4.1.3, "Identifer les requtes qui posent des
problmes", pourront vous donner des pistes damlioration.
9.1.1 Ajustement de la mmoire utilisable
La plupart des SGBDR intgrent un paramtre permettant de confgurer la quantit
maximale de mmoire quils peuvent utiliser. Il faut veiller ce que ces paramtres
ntouffent pas le serveur (il ne faut pas swapper ces zones), mais il faut que le
SGBDR utilise au mieux la mmoire disponible sur le serveur.
Sous Oracle 10g, le paramtre sga_target peut tre utilis.
Sous Oracle 11g, les paramtres memory_target et memory_max_target peuvent
tre utiliss.
Sous SQL Server, le paramtre max server memory peut tre utilis.
Sous MySQL, de nombreux paramtres sont disponibles parmi lesquels: key_
buffer_size, innodb_buffer_pool_size, innodb_additional_memory_pool_
size, innodb_log_buffer_size, query_cache_size.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
224 Autres pistes doptimisation Axe 3
Normalement, sous Oracle et SQL Server, ces paramtres sont automatiquement
confgurs en fonction de la mmoire disponible au moment de linstallation. la
suite dun changement de confguration ou pour des raisons diverses, ils peuvent
avoir une valeur inadapte et ainsi sous-utiliser les ressources disponibles du serveur.
Jai plusieurs fois eu loccasion de constater chez des clients que la base de donnes
manquait de mmoire alors que le serveur avait encore1 ou 2Go de mmoire vive
disponible. Le cas le plus rcent tait sur un serveur destin la base de donnes
avec 2Go de RAM, la mmoire maximale utilisable tait confgure 512Mo alors
que 1,5Go aurait t plus adapt.
9.1.2 Rpartition des fchiers
Rpartir les fchiers de donnes, de contrle et de journalisation, sur des disques
diffrents amliore gnralement les performances en lecture et en criture. Pour
les fchiers de contrle Oracle, cette pratique est recommande pour des raisons de
fabilit.
Rpartir les donnes et les index sur des tablespaces qui sont sur des disques diff-
rents est une bonne pratique assez rpandue.
9.2 Optimisation matrielle
Cette tche est plutt dans le primtre du DBA et de ladministrateur systme,
cependant nous allons ici survoler quelques pistes.
Un des moyens damliorer les performances est damliorer le matriel utilis pour
faire tourner le SGBDR. Cette solution devrait tre envisage seulement lorsque
toutes les autres ont t puises (do la localisation de ce chapitre la fn de
louvrage). Malheureusement, pour des raisons de simplicit, cest souvent une des
premires tre mises en uvre. Nous allons rapidement tudier les impacts de
lamlioration des lments cls.
9.2.1 Le CPU
De faon gnrale, lamlioration du CPU aura toujours un rsultat positif, du fait
quil est un point de passage systmatique pour toutes les oprations. Cependant,
cest rarement le point qui rsoudra les gros problmes de performances moins
davoir un trs vieux serveur.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre 9 Optimisation de linfrastructure 225
Laugmentation du nombre de CPU naura gnralement dimpact signifcatif que
sil y a plusieurs utilisateurs ou des excutions de requtes en parallle.
9.2.2 La mmoire vive (RAM)
La quantit de RAM sur les serveurs de base de donnes est souvent le nerf de la
guerre. Cest elle qui permet daugmenter la taille du cache (voir Chapitre1, sec-
tion1.2.6, "Le cache mmoire"). Il est frquent de voir des systmes avec plusieurs
gigaoctets de RAM (les SGBDR sont les plus demandeurs darchitectures 64bits).
Lcart de performances entre une requte portant sur un volume de donnes tenant
en RAM et une requte ncessitant de nombreux accs disque est norme. Pour
mmoire:
Un accs disque moyen est de lordre de 10ms de latence avec un dbit de quelques
Mo/s.
Un accs RAM est de lordre de quelques nanosecondes avec un dbit de quelques
Go/s.
Laugmentation de la RAM est souvent lamlioration matrielle la plus effcace.
9.2.3 Le sous-systme disque
Les donnes viennent des disques et repartent sur les disques une fois quelles sont
modifes. Si elles sont trop grosses pour tenir en RAM, les performances du sous-
systme disque sont critiques.
Une premire solution consiste amliorer les performances intrinsques des
disques:
vitesse rotation 15000 tours/min;
interface haut dbit SCSI/SAS;
gros cache interne;
disques SSD (Solid State Disk, Flash).
Une autre solution consiste utiliser des systmes RAID. La mise en uvre des
techniques de mirroring et de stripping permettra daugmenter les dbits. Certains
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
226 Autres pistes doptimisation Axe 3
modes RAID peuvent lgrement dgrader les performances en criture (RAID5) et
ne sont donc pas recommands pour les fchiers de journalisation.
Une dernire solution, plus simple mettre en uvre, consiste rpartir les donnes
sur plusieurs disques (avec ou sans RAID) afn de maximiser les dbits.
9.2.4 Le rseau
Les changes avec un SGBDR sont gnralement composs de trs nombreux petits
changes (mme sil peut y en avoir des gros). Le facteur cl ct rseau sera la
latence.
Sur un LAN (Local Area Network), il ny a gnralement pas de problme, mais
lutilisation dune application client/serveur sur un WAN (Wide Area Network) peut
trs vite devenir dsastreuse.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Conclusion
Au long de cet ouvrage, nous avons tudi de nombreuses solutions pour rsoudre
des problmes de performances. Je tiens, dans cette conclusion, vous rappeler une
dernire fois quelques principes.
Dans la vie, toute mdaille a son revers:
Souvent une optimisation aura des consquences. Le tout est de savoir si elles
sont mineures ou pas par rapport au gain apport.
Il faudra chaque fois rfchir aux consquences possibles et savoir si elles sont
acceptables pour votre situation.
Les consquences peuvent tre de nature diffrente:
espace disque supplmentaire requis;
ralentissement des critures;
ralentissement d'autres requtes;
ralentissement de la mme requte avec d'autres valeurs;
rduction de la capacit monter en charge;
etc.
Certains principes sont formidables sur le papier mais, dans la ralit, ils peuvent
dboucher sur des contre-performances. Faites preuve de pragmatisme et dobjec-
tivit. Ayez toujours un regard critique sur ce qui se passe quand vous valuez une
optimisation.
Il faut toujours avoir en tte que la nature des donnes, les volumes concerns,
la diversit des utilisateurs et bien dautres paramtres peuvent dboucher sur des
situations autres que celles que nous venons de rencontrer et que cela peut faire
mentir les plus belles explications.
Cet ouvrage nest pas un grimoire de magie plein de formules, mais un livre qui
donne des cls pour comprendre les mcanismes des bases de donnes et les pistes
damlioration les plus communes.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
228 Optimisation des bases de donnes
Le plus important est que vous dveloppiez, au fl du temps, un talent danalyse, qui
vous permettra de comprendre des situations diverses et parfois complexes. Ll-
ment le plus important pour optimiser une base de donnes, cest vous.
Jespre que ce livre vous aura aid dvelopper votre talent.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Annexes
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
A
Gestion interne
des enregistrements
A.1 Le RowID
Le RowID est une information permettant dadresser un enregistrement au sein de
la base de donnes (voir Chapitre1, section1.2.2, "Le RowID").
Le RowID dun enregistrement sobtient en interrogeant la pseudo-colonne rowid et
il ressemble cela AAARnUAAGAAASIfAAG.
Quand les enregistrements sont dans un mme bloc, les RowID se suivent. Lors des
changements de blocs, les trois derniers caractres repartent de AAA, et la partie
prcdente du rowid change. On voit ci-aprs un changement de bloc:
SQL> select noclient, nom, prenom, rowid from clients;
NOCLIENT NOM PRENOM ROWID
---------- -------------- ----------- ------------------
. . . . .
14989 Humphrey Carlos AAARdSAAGAAAGg0ABA
14992 Harry Anna AAARdSAAGAAAGg0ABB
14995 Beckham Bobbi AAARdSAAGAAAGg0ABC
14998 Stone Mos AAARdSAAGAAAGg0ABD
15001 Foster Boyd AAARdSAAGAAAGg0ABE
15004 Iglesias Lance AAARdSAAGAAAGg0ABF
15007 Webb Tia AAARdSAAGAAAGg0ABG
15010 Viterelli Hope AAARdSAAGAAAGg0ABH
15013 Dern Hope AAARdSAAGAAAGg0ABI
15016 Sepulveda Al AAARdSAAGAAAGg1AAA
15019 Marshall Pierce AAARdSAAGAAAGg1AAB
15022 Leoni Donna AAARdSAAGAAAGg1AAC
15025 Navarro Candice AAARdSAAGAAAGg1AAD
15028 Krieger Rip AAARdSAAGAAAGg1AAE
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
232 Annexes
15031 Waite Winona AAARdSAAGAAAGg1AAF
15034 Sylvian Carolyn AAARdSAAGAAAGg1AAG
15037 Paige Curtis AAARdSAAGAAAGg1AAH
. . . . .
Le package DBMS_ROWID permet de manipuler et de dcoder ces donnes, comme
dans cet exemple:
DECLARE
ridtyp NUMBER;
objnum NUMBER;
relfno NUMBER;
blno NUMBER;
rowno NUMBER;
rid ROWID;
infos varchar2(200);
tabspace varchar2(200);
BEGIN
SELECT rowid INTO rid FROM bigemp where empno=52900;
dbms_rowid.rowid_info(rid,ridtyp,objnum,relfno,blno,rowno);
select t.object_type||' '||t.owner||'.'||t.object_name,ta.tablespace_name
into infos,tabspace
from sys.dba_objects t,sys.dba_tables ta
where t.object_id=objnum and t.owner=ta.owner
and t.object_name=ta.table_name;
dbms_output.put_line('Type RowID:' || TO_CHAR(ridtyp));
dbms_output.put_line('No Objet :' || TO_CHAR(objnum) ||' - '||infos||'
Tablespace:'||tabspace);
select le_name into infos from sys.dba_data_les
where relative_fno=6 and tablespace_name=tabspace;
dbms_output.put_line('Datale :' || TO_CHAR(relfno) ||' - '||infos);
dbms_output.put_line('No Block :' || TO_CHAR(blno));
dbms_output.put_line('No ligne :' || TO_CHAR(rowno));
END;
Le rsultat est le suivant:
Type RowID:1
No Objet :71232 - TABLE SCOTT.BIGEMP Tablespace:BIG_TABLESPACE
Datale :6 - E:\ORACLE\ORADATA\ORCL\BIG_TABLESPACE1
No Block :75965
No ligne :2
A.2 Row Migration et Row Chaining
Nous dtaillons ici les mcanismes de Row Migration et de Row Chaining (voir
Chapitre 1, section 1.2.5, "Row Migration et Row Chaining") en les tudiant de
faon pratique au moyen de la table suivante:
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre A Gestion interne des enregistrements 233
CREATE TABLE row_mig_chain_demo (
Cle int PRIMARY KEY,
col1 VARCHAR2(4000),
col2 VARCHAR2(4000),
col3 VARCHAR2(4000),
col4 VARCHAR2(4000) );
Cration de deux enregistrements qui tiennent dans le mme bloc
INSERT INTO row_mig_chain_demo (cle,col1) VALUES (1,lpad('A',3000,'X'));
INSERT INTO row_mig_chain_demo (cle,col1) VALUES (2,lpad('A',3000,'X'));
select t.cle,t.rowid from row_mig_chain_demo t;
CLE ROWID
--- ------------------
1 AAASGpAAHAAAIOnAAA
2 AAASGpAAHAAAIOnAAB
Si on analyse les donnes de cette table:
analyze table ROW_MIG_CHAIN_DEMO compute statistics;
SQL> select table_name,num_rows,blocks,empty_blocks,avg_space,chain_cnt,avg_
row_len
2 from sys.user_tables where table_name='ROW_MIG_CHAIN_DEMO';

TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN
------------------ -------- ------ ------------ ---------- ---------- -----------
ROW_MIG_CHAIN_DEMO 2 5 3 6869 0 3009
on constate que, dans Chain_Cnt, il ny a pas de chanage dans cette table.
Nous allons agrandir un enregistrement afn que les deux ne puissent plus tenir dans
le bloc de 8Ko:
UPDATE row_mig_chain_demo SET col2 = lpad('A',4000,'X') WHERE cle = 1;
Lanalyse des donnes de cette table:
analyze table ROW_MIG_CHAIN_DEMO compute statistics;
SQL> select table_name,num_rows,blocks,empty_blocks,avg_space,chain_cnt,avg_
row_len
2 from sys.user_tables where table_name='ROW_MIG_CHAIN_DEMO';

TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN
------------------ --------- ------ ------------ ---------- ---------- -----------
ROW_MIG_CHAIN_DEMO 2 5 3 6059 1 5013
montre que, prsent, Chain_Cnt=1. Il y a donc eu Row Migration.
Si on "dfragmente" la table:
alter table row_mig_chain_demo move;
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
234 Annexes
et quon analyse de nouveau les donnes de la table:
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN
------------------ -------- ------ ------------ ---------- ---------- -----------
ROW_MIG_CHAIN_DEMO 2 5 3 3033 0 5010
on voit que Chain_Cnt revient 0. Il ny a plus de chanage et les donnes sont dans
deux blocs distincts, comme le montrent les RowID ci-aprs.
select t.cle,t.rowid from row_mig_chain_demo t;
CLE ROWID
--- ------------------
1 AAASGuAAHAAAIOlAAA
2 AAASGuAAHAAAIOkAAA
Si on agrandit une ligne au point quelle ne puisse plus tenir dans un bloc:
UPDATE row_mig_chain_demo SET col3 = lpad('A',3000,'X') WHERE cle = 1;
UPDATE row_mig_chain_demo SET col4 = lpad('A',3000,'X') WHERE cle = 1;
et quon analyse une nouvelle fois les donnes de la table:
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN
------------------ -------- ------ ------------ ---------- ---------- -----------
ROW_MIG_CHAIN_DEMO 2 8 0 4841 1 8016
nous voyons quun chanage rapparat dans la colonne Chain_Cnt. Si on "dfrag-
mente" la table nouveau, il y a toujours un chanage (voir ci-aprs). Cela est d
au fait que les donnes ne peuvent pas tenir dans un bloc unique car leur taille est
suprieure. Le chanage sera permanent.
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN
------------------ -------- ------ ------------ ---------- ---------- -----------
ROW_MIG_CHAIN_DEMO 2 6 2 2688 1 8025
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
B
Statistiques sur les donnes
plus en dtail
Comme nous lavons vu au Chapitre5, section5.1, "Statistiques sur les donnes",
les statistiques sont un lment fondamental pour lutilisation du CBO (Cost Based
Optimiser). Nous allons tudier ici plus en dtail la nature des statistiques utilises
par Oracle.
B.1 Statistiques selon l'ancienne mthode de collecte
Lancienne mthode de collecte des statistiques les stocke dans les tables du diction-
naire de donnes, grce linstruction suivante.
analyze table <NomTable> compute statistics;
Les statistiques sont consultables avec les requtes suivantes:
ListingB.1: Statistiques au niveau de la table
select t.table_name,t.num_rows,t.blocks, t.empty_blocks,t.avg_space,t.chain_
cnt,t.avg_row_len
from sys.user_tables t where t.table_name like 'BIG%';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE CHAIN_CNT AVG_ROW_LEN
----------- --------- ------- ------------ ---------- ---------- -----------
BIGDEPT 400004 1630 0 0 0 22
BIGEMP 1400014 10097 0 0 0 44
On y voit le nombre de lignes et de blocs utiliss ainsi que la taille moyenne dune
ligne. Ces informations contribuent estimer le nombre dentres/sorties disque.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
236 Annexes
ListingB.2: Statistiques au niveau des index
select t.index_name, t.num_rows ,t.blevel, t.leaf_blocks, t.distinct_keys ,t.
avg_leaf_blocks_per_key, t.avg_data_blocks_per_key,t.clustering_factor
from sys.user_indexes t where t.table_name like 'BIG%';
INDEX_NAME NUM_ROWS BLEVEL LEAF_BLOCKS DISTINCT_KEYS AVG_LEAF_BLOCKS_PER_KEY AVG_DATA_BLOCKS_PER_KEY CLUSTERING_FACTOR
----------------- -------- ------ ---------- ------------ ---------------------- ----------------------- -----------------
PK_BIGEMP 1400014 2 3103 1400014 1 1 9502
IS_BIGEMP_DEPT 1400014 2 3298 301920 1 1 38416
PK_BIGDEPT 400004 2 886 400004 1 1 1540
IS_BIGDEPT_LOC 400004 2 1375 400004 1 1 6261
ListingB.3: Statistiques au niveau des colonnes
select t.table_name,t.column_name,t.num_distinct,t.low_value,t.high_value
,t.density,t.num_nulls
from sys.user_tab_cols t where t.table_name like 'BIG%'
order by t.table_name,t.column_id;
TABLE_NAME COLUMN_NAME NUM_DISTINCT LOW_VALUE HIGH_VALUE DENSITY NUM_NULLS
---------- ------------ ------------ ------------------- ---------------- ---------- ----------
BIGDEPT DEPTNO 400004 C10B C40B010129 2,49997E-6 0
BIGDEPT DNAME 4 4143434F554E54494E47 53414C4553 0,25 0
BIGDEPT LOC 5 424F53544F4E 546F756C6F757365 0,2 0
BIGEMP EMPNO 1400014 C24A46 C50201015023 7,14278E-6 0
BIGEMP ENAME 14 4144414D53 57415244 0,0714285 0
BIGEMP JOB 5 414E414C595354 53414C45534D414E 0,2 0
BIGEMP MGR 597824 C24C43 C50201015003 1,67273E-6 100001
BIGEMP HIREDATE 13 77B40C11010101 77BB0517010101 0,07692307 0
BIGEMP SAL 34 C211 C3020F1B 0,02941176 0
BIGEMP COMM 4 80 C20F 0,25 1000010
BIGEMP DEPTNO 301920 C10B C40B01011F 3,31213E-6 0
Ces donnes serviront principalement estimer limpact de chaque condition.
B.2 Statistiques selon la nouvelle mthode de collecte
prsent, il est recommand dutiliser le package DBMS_STATS qui donne un niveau
dinformation plus lev. Les statistiques sont stockes dans des tables ddies.
ListingB.4: Statistiques DBMS_STATS sur les tables
select * from sys.user_tab_statistics
where table_name='BIGEMP'
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre B Statistiques sur les donnes plus en dtail 237
Nom champ Valeur
TABLE_NAME BIGEMP
PARTITION_NAME
PARTITION_POSITION
SUBPARTITION_NAME
SUBPARTITION_POSITION
OBJECT_TYPE TABLE
NUM_ROWS 1400014
BLOCKS 10097
EMPTY_BLOCKS 0
AVG_SPACE 0
CHAIN_CNT 0
AVG_ROW_LEN 44
AVG_SPACE_FREELIST_BLOCKS 0
NUM_FREELIST_BLOCKS 0
AVG_CACHED_BLOCKS
AVG_CACHE_HIT_RATIO
SAMPLE_SIZE 1400014
LAST_ANALYZED 27/03/2010 11:00:44
GLOBAL_STATS YES
USER_STATS NO
STATTYPE_LOCKED
STALE_STATS YES
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
238 Annexes
ListingB.5: Statistiques DBMS_STATS sur les index
select * from sys.user_ind_statistics
where table_name='BIGEMP'
Nom champ Valeur
INDEX_NAME PK_BIGEMP
TABLE_OWNER SCOTT
TABLE_NAME BIGEMP
PARTITION_NAME
PARTITION_POSITION
SUBPARTITION_NAME
SUBPARTITION_POSITION
OBJECT_TYPE INDEX
BLEVEL 2
LEAF_BLOCKS 3103
DISTINCT_KEYS 1400014
AVG_LEAF_BLOCKS_PER_KEY 1
AVG_DATA_BLOCKS_PER_KEY 1
CLUSTERING_FACTOR 9502
NUM_ROWS 1400014
AVG_CACHED_BLOCKS
AVG_CACHE_HIT_RATIO
SAMPLE_SIZE 1400014
LAST_ANALYZED 27/03/2010 11:00:49
GLOBAL_STATS YES
USER_STATS NO
STATTYPE_LOCKED
STALE_STATS YES
ListingB.6: Statistiques DBMS_STATS sur les colonnes
select * from sys.user_tab_col_statistics t
where t.table_name like 'BIG%';
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre B Statistiques sur les donnes plus en dtail 239
Nom champ Valeur
TABLE_NAME BIGEMP
COLUMN_NAME EMPNO
NUM_DISTINCT 1400014
LOW_VALUE C24A46
HIGH_VALUE C50201015023
DENSITY 7,14278571499999E-7
NUM_NULLS 0
NUM_BUCKETS 1
LAST_ANALYZED 27/03/2010 11:00:23
SAMPLE_SIZE 1400014
GLOBAL_STATS YES
USER_STATS NO
AVG_COL_LEN 6
HISTOGRAM NONE
Les tables contenants des statistiques DBMS_STATS sont:
DBA_TABLES, DBA_OBJECT_TABLES, DBA_TAB_STATISTICS
DBA_TAB_COL_STATISTICS, DBA_TAB_HISTOGRAMS, DBA_INDEXES
DBA_IND_STATISTICS, DBA_CLUSTERS, DBA_TAB_PARTITIONS
DBA_TAB_SUBPARTITIONS, DBA_IND_PARTITIONS,
DBA_IND_SUBPARTITIONS, DBA_PART_COL_STATISTICS,
DBA_PART_HISTOGRAMS,
DBA_SUBPART_COL_STATISTICS, DBA_SUBPART_HISTOGRAMS
Avec leurs dclinaisons USER_* et ALL_*
Au-del de loptimisation, certaines de ces statistiques peuvent tre utiles pour pren-
dre en main une base de donnes. En effet, elles aident reprer facilement les plus
grosses tables, les colonnes qui ne sont jamais remplies,etc.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
240 Annexes
B.3 Histogrammes
Nous dtaillons ici les informations stockes dans les histogrammes tudis au
Chapitre5, section5.1.3,"Slectivit, cardinalit, densit".
ListingB.7: Statistiques DBMS_STATS sur les histogrammes de frquence
select endpoint_number-nvl(lag(endpoint_number,1)OVER (ORDER BY endpoint_
number ),0) TailleIntervalle
,endpoint_number, endpoint_value
from user_tab_histograms t
where table_name='BIGDEPT' and column_name = 'LOC'
La colonne TailleIntervalle est calcule partir des valeurs courante et prcdente
du Endpoint.
endpoint_value est une reprsentation numrique de la chane de caractres.
TailleIntervalle endpoint_number endpoint_value
99900 99900 344 300 505 052 090 000 000 000 000 000 000 000
99900 199800 349 350 027 483 572 000 000 000 000 000 000 000
99900 299700 354 400 587 944 790 000 000 000 000 000 000 000
99900 399600 406 405 544 089 997 000 000 000 000 000 000 000
404 400004 438 413 586 837 071 000 000 000 000 000 000 000
Lhistogramme de distribution coupe les donnes en ntranches gales et dtermine
les bornes des tranches.
ListingB.8: Statistiques DBMS_STATS sur les histogrammes de distribution
select endpoint_number, endpoint_value from user_tab_histograms
where table_name='BIGDEPT' and column_name = 'DEPTNO';
endpoint_number endpoint_value
0 10
1 1000010
2 2000020
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre B Statistiques sur les donnes plus en dtail 241
endpoint_number endpoint_value
3 3000030
4 4000040
5 5000040
6 6000040
7 7000040
8 8000040
9 9000040
10 10000040
Normalement, le SGBDR dtecte les colonnes sur lesquelles il est pertinent de
calculer un histogramme. Cependant, vous pouvez forcer les histogrammes avec
l'instruction suivante:
execute dbms_stats.gather_table_stats(user,'bigdept',cascade => true
,estimate_percent =>100,method_opt => 'for all columns size 100');
Cest le SGBDR qui dterminera le type dhistogramme en fonction du nombre de
valeurs. Il est possible que votre histogramme forc disparaisse lors de la prochaine
collecte automatique des statistiques.
B.4 Facteur de foisonnement (Clustering Factor)
Nous allons tudier ici limpact du facteur de foisonnement.
La constitution de la table bigemp a t conscutive la cration squentielle des
enregistrements ; la table bigemp2 a t cre la suite du tri des donnes par la
colonne Ename. Les squences dEmpno sont donc rparties de faon occuper
successivement un 1/14 de tables diffrentes
1
.
create table bigemp2 as select * from bigemp order by ename;
alter table bigemp2 add constraint PK_bigemp2 primary key(empno);
execute dbms_stats.GATHER_TABLE_STATS('SCOTT','BIGEMP2');
1. Rappel: la table bigemp est 100 000 fois la rptition des 14lignes de la table emp avec des offsets sur
les Empno et Deptno.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
242 Annexes
ListingB.9: Statistiques des index de cl primaire de BIGEMP et BIGEMP2
select t.INDEX_NAME,t.LEAF_BLOCKS,t.DISTINCT_KEYS,t.CLUSTERING_FACTOR from
sys.user_ind_statistics t
where index_name like 'PK_BIGEMP%';
INDEX_NAME LEAF_BLOCKS DISTINCT_KEYS CLUSTERING_FACTOR
-------------------------------- ----------- ------------- -----------------
PK_BIGEMP 3103 1400014 9502
PK_BIGEMP2 3103 1400014 1399950
On voit que lindex sur bigemp a un bon facteur de foisonnement puisquil y a en
moyenne trois liens par feuille, alors que le deuxime index a presque autant de liens
que denregistrements. Dans ce cas, dans chaque feuille, chaque cl pointe sur un
bloc du tas de la table diffrent.
Dmonstration par la pratique: cette requte, excute sur les deux tables, met un
critre sur Empno pour utiliser lindex et un autre sur la colonne Ename afn de
forcer un accs au tas, sinon seul lindex serait utilis vu que nous effectuons un
count(*).
Select count(*) from BigEmp
where empno between 10000000 and 20000000
and ename='MILLER';
FigureB.1
Sur table BIGEMP avec index
ayant un faible taux de
foisonnement (temps
d'excution 160ms).
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre B Statistiques sur les donnes plus en dtail 243
FigureB.2
Sur table BIGEMP2 avec
index ayant un fort taux
de foisonnement (temps
d'excution 440ms).
On voit ici limpact dun mauvais Clustering Factor (Timing 3 et Consistent
Gets100).
Loptimiseur redoute tellement ces rsultats quil nutilise pas lindex ds que le
clustering factor est mauvais. Dailleurs, pour obtenir ce plan, nous avons d insrer
le hint index_rs dans la requte. Sans cela, loptimiseur choisirait de faire un Full
Table Scan qui provoque moins de Consistent Gets (9600) mais un temps dexcution
de 1,37seconde.
Select /*+index_rs(e)*/ count(*) from BigEmp2 e
where empno between 10000000 and 20000000
and ename='MILLER'
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
C
Scripts de cration des tables
detest bigemp et bigdept
Les tables de test nous permettent deffectuer des tests sur une base simple mais de
taille suffsamment importante pour mettre en vidence lintrt des optimisations.
La base livre est tlchargeable sur le site de lauteur http://www.altidev.com/
livres.php. Sous Oracle, les bases bigdept et bigemp sont gnres laide des
scripts suivants.
Ces tables sont fondes sur les tables exemples dOracle prsentes dans le schma
SCOTT de la base dexemple mais dupliques 100 000 fois, dans laquelle nous
avons introduit quelques valeurs particulires.
Je vous conseille de les crer dans un tablespace spar, par exemple un tablespace
nomm BIG_TABLESPACE qui aurait une taille de 1Go.
Nhsitez pas adapter les tailles votre environnement, pour que cela soit le plus
signifcatif sans que chaque test soit trop long.
ListingC.1: Fichier CreateBig.SQL
-- Cration de la table BigDept
Create Table bigDEPT (
DEPTNO Number ,
DNAME VARCHAR2(14),
LOC VARCHAR2(13) )
Tablespace BIG_TABLESPACE ;
-- Remplissage de la table
begin
for i in 0..100000
loop
insert into bigdept
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
246 Annexes
select i*100+deptno, dname, decode(mod(i, 1000),0,'Toulouse',loc)
from dept;
end loop;
commit;
end;
/
-- Ajout de la cl primaire
alter table bigDEPT add constraint PK_bigDEPT Primary Key(Deptno);
-- Cration de la table BigEmp
CREATE TABLE bigEMP (
EMPNO NUMBER ,
ENAME VARCHAR2(10) NOT NULL CHECK (ename=UPPER(ename)),
JOB VARCHAR2(9),
MGR NUMBER ,
HIREDATE DATE,
SAL NUMBER(7,2) CHECK (SAL > 500 ),
COMM NUMBER(7,2),
DEPTNO NUMBER NOT NULL )
Tablespace BIG_TABLESPACE ;
-- Insertion des lignes
begin
for i in 0..100000
loop
insert into bigemp
select i*1000+empno, ename, job, i*1000+mgr, hiredate, sal, comm,
i*100+deptno
from emp;
end loop;
commit;
end;
/
-- Ajout de la cl primaire et des foreign key
alter table bigEMP add (
constraint PK_BIGEMP primary key(empno),
constraint fk_bigemp_dpt foreign key (deptno) REFERENCES bigdept (deptno),
constraint fk_bigemp_emp foreign key (mgr) REFERENCES bigemp (empno)
);
Si vous navez pas le schma SCOTT sur votre base Oracle, et donc pas les tables
dept et emp, voici le script pour les recrer.
ListingC.2: Fichier CreateEmpDept.SQL
Create Table DEPT (
DEPTNO Number(2,0) constraint PK_DEPT Primary Key,
DNAME VARCHAR2(14),
LOC VARCHAR2(13));
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Chapitre C Scripts de cration des tables detest bigemp et bigdept 247
Insert into DEPT values ('10','ACCOUNTING','NEW YORK');
Insert into DEPT values ('20','RESEARCH','DALLAS');
Insert into DEPT values ('30','SALES','CHICAGO');
Insert into DEPT values ('40','OPERATIONS','BOSTON');
Commit;
CREATE TABLE EMP (
EMPNO NUMBER(4) PRIMARY KEY,
ENAME VARCHAR2(10) NOT NULL CHECK (ename=UPPER(ename)),
JOB VARCHAR2(9),
MGR NUMBER(4) REFERENCES emp (empno),
HIREDATE DATE,
SAL NUMBER(7,2) CHECK (SAL > 500 ),
COMM NUMBER(7,2),
DEPTNO NUMBER(2) NOT NULL REFERENCES dept (deptno) );
Insert into EMP values (7839,'KING','PRESIDENT',NULL ,TO_
DATE('17/11/1981','DD/MM/YYYY'),5000,NULL,10);
Insert into EMP values (7566,'JONES','MANAGER',7839 ,TO_DATE('02/04/1981',
'DD/MM/YYYY'),2975,NULL,20);
Insert into EMP values (7698,'BLAKE','MANAGER',7839, TO_DATE('01/05/1981',
'DD/MM/YYYY'),2850,NULL,30);
Insert into EMP values (7782,'CLARK','MANAGER',7839 ,TO_DATE('09/06/1981',
'DD/MM/YYYY'),2450,NULL,10);
Insert into EMP values (7902,'FORD','ANALYST',7566 ,TO_DATE('03/12/1981',
'DD/MM/YYYY'),3000,NULL,20);
Insert into EMP values (7369,'SMITH','CLERK',7902 ,TO_DATE('17/12/1980',
'DD/MM/YYYY'),800,NULL,20);
Insert into EMP values (7499,'ALLEN','SALESMAN',7698 ,
TO_DATE('20/02/1981','DD/MM/YYYY'),1600,300,30);
Insert into EMP values (7521,'WARD','SALESMAN',7698 ,TO_DATE('22/02/1981',
'DD/MM/YYYY'),1250,500,30);
Insert into EMP values (7654,'MARTIN','SALESMAN',7698 ,
TO_DATE('28/09/1981','DD/MM/YYYY'),1250,1400,30);
Insert into EMP values (7788,'SCOTT','ANALYST',7566 ,TO_DATE('19/04/1987',
'DD/MM/YYYY'),3000,NULL,20);
Insert into EMP values (7844,'TURNER','SALESMAN',7698 ,TO_
DATE('08/09/1981','DD/MM/YYYY'),1500,0,30);
Insert into EMP values (7876,'ADAMS','CLERK',7788 ,TO_DATE('23/05/1987',
'DD/MM/YYYY'),1100,NULL,20);
Insert into EMP values (7900,'JAMES','CLERK',7698 ,TO_DATE('03/12/1981',
'DD/MM/YYYY'),950,NULL,30);
Insert into EMP values (7934,'MILLER','CLERK',7782 ,TO_DATE('23/01/1982',
'DD/MM/YYYY'),1300,NULL,10);
commit;
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
D
Glossaire
DBA (DataBase Administrator). Dsigne les personnes qui sont charges de ladmi-
nistration de la base de donnes.
DDL (Data Defnition Language). Voir LDD.
DML (Data Manipulation Language). Voir LMD.
E/S (Entres/Sorties). Dsigne les changes vers le sous-systme de stockage, cest-
-dire gnralement les disques durs. On peut aussi parler dE/S rseau pour dsigner
les changes de donnes vers dautres machines travers le rseau.
Entit. Dsigne une table dans la terminologie du modle entit/association.
I/O (Input/Output). Voir E/S.
Index. Principal objet doptimisation des performances, largement abord dans cet
ouvrage.
Heap (tas). Type dorganisation des donnes.
HOT (Heap Organized Table). Dsigne les tables organises en tas.
LDD (langage de dfnition des donnes). Sous-ensemble du SQL couvrant les
instructions permettant de modifer les structures des donnes, principalement
lesinstructions CREATE, ALTER et DROP.
LMD (langage de manipulation des donnes). Sous-ensemble du SQL couvrant
les instructions permettant de modifer les donnes, principalement les instructions
INSERT, UPDATE et DELETE.
LOB. Dsigne les types de grande capacit (Large OBject); ils peuvent tre textuels
ou binaires.
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
250 Annexes
OLAP (OnLine Analytical Processing). Dsigne les bases de donnes dites "analy-
tiques", servant gnralement lanalyse des donnes. Elles contiennent gnrale-
ment des donnes issues de bases de donnes OLTP. Elles en diffrent par leur
structure, le volume ou le niveau de dtails des informations quelles contiennent.
OLTP (OnLine Transaction Processing). Dsigne les bases de donnes dites "trans-
actionnelles", servant gnralement pour le traitement oprationnel des donnes.
Oracle RAC (Real Application Cluster). Dsigne lutilisation dOracle sur plusieurs
serveurs qui partagent un disque dur.
RDBMS (Relational Database Management System). Voir SGBDR.
Relation. Dsigne une table dans la terminologie du modle relationnel tel quil a
t tabli par Edgar Frank Codd.
SGBDR (systme de gestion de base de donnes relationnelle). Dsigne un systme
(logiciel) qui permet de grer une base de donnes relationnelle.
Table. Structure principale permettant de stocker les donnes dans une base de
donnes.
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Index
A
Analytique 194
ANALYZE 78
Anti-jointure 156
Autotrace 51
AWR 62
B
Binding 219
Buffer cache 13
BULK COLLECT 200
C
Cache de donnes 210
Cache mmoire 13
Cardinalit 80
CBO 16
Cluster 132
Clustered Index 127
Clustering Factor 98
Compilation 212
Compression
Index 94
index bitmap 101
LOB 121
Table 119
Consistent Gets 53
CONTAINS 113
CONTEXT 112
CTXCAT 113
Cube Group By 189
D
Datafle 7
DBMS_APPLICATION_INFO 68
DBMS_MONITOR 68
DBMS_PROFILER 212
DBMS_STATS 78
Dnormalisation 38
Densit 80
Direct Path 198
Donnes, cache de 210
DYNAMIC_SAMPLING 82
E
explain plan for 55
Extent 8
F
Facteur de foisonnement 98
Fast Full Scan 57
fonction analytique 194
FORALL 203
Full Table Scan 56
G
Grouping Sets 186
H
Hash Join 58
HAVING 162
Heap 11, 87
Hint 177
Histogramme 83
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
252 Optimisation des bases de donnes
I
Index 14, 85
bitmap 101
Bitmap Join 108
B*Tree 86
clustered 127
colonnes incluses 97
composite 90
compression 94
fonction 99
full text 113
hints 180
multicolonnes 90
reconstruction 150
Reverse 100
IOT 122
L
LIKE 80, 112
M
Materialized Views 146
MCD 23
Mdiane 194
mmoire, cache 13
MERGE 195, 196
Merge Join 58
MLD 24
MPD 24
N
Nested Loop 57
NOLOGGING 165
Normalisation 33
O
Optimizer goal 17
Or Expansion 154
P
PARRALEL QUERY 184
Parsing 15
Partitionnement 135
PCTFREE 118
Physical Reads 53
Plan d'excution 15, 55
PL/SQL 200
compilation 212
Predicate push 154
Profling 212
Q
Query Rewriting 147
Query Transformation 154
R
Range Scan 57
Ranking 192
Reconstruction
index 150
table 149
requtes, rcriture 153
Rollup Group By 188
Row Chaining 12
RowID 10
Row Migration 12
S
Segment 8
Slectivit 80
SGBDR 6
Skip Scan 57, 91
SQL Access Advisor 66
SQL Trace 67
SQL Tuning Advisor 66
Statistiques 77
tendues 84
Statspack 62
Subquery unesting 154
Openmirrors.com
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Index 253
T
Tablespace 7, 118
Tas 11, 87
tkprof 69
Trace Analyzer 71
Transformation de requtes 154
Trigger 198
Typage 25
U
Unique Scan 57
V
V$sql 61
View merging 154
Vue matrialise 146
W
WITH 191
Proprit de Albiri Sigue <tag.tog@gmail.com> customer 27921 at Fri Mar 11 19:20:10 +0100 2011
Cet ouvrage a pour objectif de mettre la porte des
dveloppeurs les connaissances utiles loptimisation
des bases de donnes. Cette activit est souvent cone
aux administrateurs de bases de donnes (DBA) une
fois que les projets sont termins, alors que cest au
niveau du dveloppement quil faut se pencher sur la
problmatique des performances.
De manire claire et pragmatique, lauteur expose les
diffrentes techniques en les prsentant en situation.
Pour chacune delles, il montre laide dun cas concret
ce quelle amliore et dans quel contexte elle agit
efcacement. En homme du terrain, il les compare et
prend parti.
Louvrage se fonde pour une grande part sur le systme
de bases de donnes Oracle (versions 9i, 10g,
11g Release 1&2), toutefois des parallles sont fait
rgulirement avec Microsoft SQL Serveur (versions
2005 et 2008) et MySQL (version 5.1) par le biais
dencadrs et de paragraphes ddis. Les techniques
prsentes pour ces trois systmes sont communes
de nombreux autres SGBDR, le lecteur pourra ainsi
appliquer les conseils de ce livre quasiment toutes les
bases de donnes relationnelles du march.
R

r
e
n
c
e
R

r
e
n
c
e
R

r
e
n
c
e
Niveau : Intermdiaire
Conguration : Multiplate-forme
Rseaux
et tlcom
Scurit
Systme
dexploitation
Programmation
Pearson Education France
47 bis, rue des Vinaigriers
75010 Paris
Tl. : 01 72 74 90 00
Fax : 01 42 05 22 17
www.pearson.fr
bases de
donnes
Optimisation des
bases de donnes
Optimisation des
Mise en uvre sous Oracle
Mise en uvre sous Oracle
O
P
T
I
M
I
S
A
T
I
O
N

D
E
S

B
A
S
E
S

D
E

D
O
N
N

E
S

propos de lauteur :
Laurent Navarro est un dveloppeur
dapplication de base de donnes
depuis plus de 15 ans. Codirigeant
de la socit Altidev, il accompagne
des industriels dans le dveloppement
dapplications de gestion et
dinformatique industrielle.
TABLE DES MATIRES
Introduction aux SGBDR
Modle relationnel
Normalisation, base du modle
relationnel
Mthodes et outils de diagnostic
Techniques doptimisation standard
au niveau base de donnes
Techniques doptimisation standard
des requtes
Techniques doptimisation des
requtes avances
Optimisation applicative (hors SQL)
Optimisation de linfrastructure
Annexes
Laurent Navarro
Programmation
Dveloppement
web
2412-ref optimiser bases de donnees.indd 1 21/05/10 14:57
ISBN : 978-2-7440-4156-3
Openmirrors.com

Das könnte Ihnen auch gefallen