• Aucun résultat trouvé

8.2 L’interface Java/JDBC

9.1.3 Optimisations

Maintenant que nous avons une idée précise du fonctionnement d’un disque, il est assez facile de mon- trer que pour un même volume de données, le temps de lecture peut varier considérablement en fonction de facteurs tels que le placement sur le disque, l’ordre des commandes d’entrées/sorties ou la présence des données dans une mémoire cache.

Toutes les techniques permettant de réduire le temps passé à accéder au disque sont utilisées intensi- vement par les SGBD qui, répétons-le, voient leurs performances en grande partie conditionnés par ces accès. Nous étudions dans cette section les principales techniques d’optmisation mises en œuvre dans une architecture simple comprenant un seul disque et un seul processeur. Nous verrons dans la partie suivante consacrée à la technologie RAID, comment on peut tirer parti de l’utilisation de plusieurs disques.

Regroupement

Prenons un exemple simple pour se persuader de l’importance d’un bon regroupement des données sur le disque : le SGBD doit lire 5 chaînes de caractères de 1000 octets chacune. Pour une taille de bloc égale à 4096 octets, deux blocs peuvent suffire. La figure 9.3 montre deux organisations sur le disque. Dans la première chaque chaîne est placée dans un bloc différent, et les blocs sont répartis aléatoirement sur les pistes du disque. Dans la seconde organisation, les chaînes sont rassemblés dans deux blocs qui sont consécutifs sur une même piste du disque.

(b) (a)

FIG. 9.3 – Mauvaise et bonne organisation sur un disque

La lecture dans le premier cas implique 5 déplacements des têtes de lecture, et 5 délais de latence ce qui donne un temps deNYLZ-[NP\

H^]

@_2CF`Ba$ ms. Dans le second cas, on aura un déplacement, et un délai de latence pour la lecture du premier bloc, mais le bloc suivant pourra être lu instantanément, pour un temps total de 8,2 ms.

Les performances obtenues sont dans un rapport de 1 à 5, le tempsminimal s’obtenant en combinant deux optimisations : regroupement et contiguïté. Le regroupement consiste à placer dans le même bloc des données qui ont de grandes chances d’êtres lues au même moment. Les critères permettant de déterminer le regroupement des données constituent un des fondements des structures de données en mémoire secon- daire qui seront étudiées par la suite. Le placement dans des blocs contigus est une extension directe du principe de regroupement. Il permet d’effectuer des lectures séquentielles qui, comme le montre l’exemple ci-dessus, sont beaucoup plus performantes que les lectures aléatoires car elles évitent des déplacements de têtes de lecture.

Plus généralement, le gain obtenu dans la lecture de deux données b

7

etb

0

est d’autant plus impor- tant que les données sont !! proches"", sur le disque, cette proximité étant définie comme suit, par ordre décroissant :

– la proximité maximale est obtenue quandb

7

etb

0

sont dans le même bloc : elles seront alors toujours lues ensembles ;

– le niveau de proximité suivant est obtenu quand les données sont placées dans deux blocs consécu- tifs ;

– quand les données sont dans deux blocs situés sur la même piste du même disque, elles peuvent être lues par la même tête de lecture, sans déplacement de cette dernière, et en une seule rotation du disque ;

– l’étape suivante est le placement des deux blocs dans un même cylindre, qui évite le déplacement des têtes de lecture ;

– enfin si les blocs sont dans deux cylindres distincts, la proximité est définie par la distance (en nombre de pistes) à parcourir.

Les SGBD essaient d’optimiser la proximité des données au moment de leur placement sur le disque. Une table par exemple devrait être stockée sur une même piste ou, dans le cas où elle occupe plus d’une piste, sur les pistes d’un même cylindre, afin de pouvoir effectuer efficacement un parcours séquentiel.

Pour que le SGBD puisse effectuer ces optimisations, il doit se voir confier, à la création de la base, un espace important sur le disque dont il sera le seul à gérer l’organisation. Si le SGBD se contentait de demander au système d’exploitation de la place disque quand il en a besoin, le stockage physique obtenu serait extrêmement fragmenté.

Séquencement

En théorie, si un fichier occupantc blocs est stocké contiguement sur une même piste, la lecture sé- quentielle de ce fichier sera – en ignorant le temps de transfert – approximativementc fois plus efficace que si tous les blocs sont répartis aléatoirement sur les pistes du disque.

Cet analyse doit cependant être relativisée car un système est souvent en situation de satisfaire simul- tanément plusieurs utilisateurs, et doit gérer leurs demandes concuramment. Si un utilisateurd demande la lecture du fichiere

7

tandis que l’utilisateur f demande la lecture du fichier e

0

, le système alternera probablement les lectures des blocs des deux fichiers. Même s’ils sont tous les deux stockés séquentielle- ment, des déplacements de tête de lecture interviendront alors et minimiseront dans une certaine mesure cet avantage. Contrôleur disque L(1−17) L(2−23) L(1−18) L(2−24) L(1−16) L(1−16), L(1−17), L(1−18), L(2−23), L(2−24) Séquenceur L(1−16), L(2−23), L(1−18), L(2−24), L(1−17) Mémoire tampon

FIG. 9.4 – Séquencement des entrées/sorties

Le système d’exploitation, ou le SGBD, peuvent réduire cet inconvénient en conservant temporairement les demandes d’entrées/sorties dans une zone tampon (cache) et en réorganisant (séquencement) l’ordre des accès. La figure 9.4 montre le fonctionnement d’un séquenceur. Un ensemble d’ordres de lectures est reçu,

L(1-16) désignant par exemple la demande de lecture du bloc 16 sur la piste 1. On peut supposer sur cet

exemple que deux utilisateurs effectuent séparément des demandes d’entrée/sortie qui s’imbriquent quand elles sont transmises vers le contrôleur.

Pour éviter les accès aléatoires qui résultent de cette imbrication, les demandes d’accès sont stockées temporairement dans un cache. Le séquenceur les trie alors par piste, puis par bloc au sein de chaque piste, et transmet la liste ordonnée au contrôleur du disque. Dans notre exemple, on se place donc tout d’abord sur la piste 1, et on lit séquentiellement les blocs 16, 17 et 18. Puis on passe à la piste 2 et on lit les blocs 23 et 24. Nous laissons au lecteur, à titre d’exercice, le soin de déterminer le gain obtenu.

Une technique systématique pour systématiser cette stratégie est celle dite!! de l’ascenseur"". L’idée est que les têtes de lecture se déplacent régulièrement du bord de la surface du disque vers l’axe de rota- tion, puis reviennent de l’axe vers le bord. Le déplacement s’effectue piste par piste, et à chaque piste le séquenceur transmet au contrôleur les demandes d’entrées/sorties pour la piste courante.

Cet algorithme réduit au maximum de temps de déplacement des têtes puisque ce déplacement s’effec- tue systématiquement sur la piste adjacente. Il est particulièrement efficace pour des systèmes avec de très nombreux processus demandant chacun quelques blocs de données. En revanche il peut avoir des effets assez désagréables en présence de quelques processus gros consomateurs de données. Le processus qui

demande des blocs sur la piste 1 alors que les têtes viennent juste de passer à la piste 2 devra attende un temps respectable avant de voir sa requête satisfaite.

Mémoire tampon

La dernière optimisation, très largement utilisée dans tous les SGBD, est l’utilisation de mémoires tampon, ou buffer. Un buffer est un ensemble de blocs en mémoire principale qui sont des copies des blocs sur le disque. Quand le système demande à accéder à un bloc, une première inspection a lieu dans le buffer. Si le bloc s’y trouve déjà, une lecture a été évitée. Sinon on effectue la lecture et on stocke la page dans le buffer. Table de hachage Mémoire centrale Lecture disque

Gestionnaire de mémoire cache

Demande de bloc blocs

FIG. 9.5 – Mémoire cache

L’idée est donc simplement de maintenir en mémoire principale une copie aussi large que possible du disque, même si une grande partie des blocs mis ainsi dans un buffer n’est pas directement utile. Une part importante du paramétrage et de l’administration d’une base de données consiste à spécifier quelle est la part de la mémoire disponible qui peut être attribuée en permanence au SGBD. Plus cette mémoire est importante, et plus il sera possible d’y conserver une partie significative de la base, avec des gains importants en terme de performance.

Quand il reste de la place dans les buffers, on peut l’utiliser en effectuant des lectures en avance (read

ahead, ou prefetching). Une application typique de ce principe est donnée par la lecture d’une table. Comme

nous le verrons au moment de l’étude des algorithmes de jointure, il est fréquent d’avoir à lire une table séquentiellement, bloc à bloc. Il s’agit d’un cas où, même si à un moment donné on n’a besoin que d’un ou de quelques blocs, on sait que toute la table devra être parcourue. Il vaut mieux alors, au moment où on effectue une lecture sur une piste, charger en mémoire tous les blocs de la relation, y compris ceux qui ne serviront que dans quelques temps et peuvent être placés dans un buffer en attendant.