Chapitre IX Optimisation des Performances
  • IX 1 Structures de stockage des données *
    • IX 1-1 Introduction *
    • IX 1-2 Les organisations structurées de tables *
      • IX 1-2-1 Principe du HASH *
      • IX 1-2-2 Principe de l'ISAM *
      • IX 1-2-3 Principe du Btree *
    • IX 1-3 Commande pour organiser une table *
    • IX 1-4 Conseils pour l'organisation des tables *
    • IX 1-5 Utilisation des index secondaires *
    • IX 1-6 Critères de choix d'une clé ou d'un index *
    • IX 1-7 Conclusion : choix d'une structure de stockage *
  • IX 2 Optimisation des performances *
    • IX 2-1 Statistiques *
    • IX 2-2 Conseils pour écrire ses requêtes *
    • IX 2-3 Règles de performances *
    • IX 2-4 Règles de vie - concurrence *
    • IX 2-5 Mises à jour et réorganisations *
  • IX 3 Résumé des actions à entreprendre pour maintenir de bonnes performances *
    • IX 3-1 Actions sur les tables *
    • IX 3-2 Créer les index *
    • IX 3-3 Créer (mettre à jour) des statistiques *
    • IX 3-4 Réorganiser les tables système *
    • IX 3-5 Nettoyer la base elle-même *
    • IX 3-6 Tester les requêtes *

IX 1 Structures de stockage des données

IX 1-1 Introduction

Lorsqu'on crée une table et que l'on y charge des données, la table est, par défaut, implantée comme un fichier non structuré : on dit qu'elle est organisée en "tas", ou "heap" en anglais. Ceci signifie que les données vont être enregistrées à la queue leu leu, dans des pages successives du disque, dans l'ordre où elles ont été entrées.

Pour améliorer les performances, c'est-à-dire accélérer les recherches de données que l'on va faire dans cette table, on a la possibilité d'agir sur l'organisation de la table, donc en fait sur le stockage physique des données, de façon à minimiser le nombre d'entrées sorties faites sur le disque.

Par exemple, on peut chercher, d'une part, à regrouper dans les mêmes pages de stockage des données qui peuvent être fréquemment recherchées ensemble, d'autre part à se donner des moyens d'accès par clés qui permettront de retrouver l'adresse des données sur disque, en fonction d'une clé, sans avoir à parcourir toute la table.

Ces méthodes pour accélérer les recherches de données dans une table sont fournies par INGRES selon deux types :

  • le premier type de méthode consiste à passer de l'organisation heap par défaut en une organisation structurée; 
  • le deuxième type de méthode consiste à créer un fichier d'index secondaire, c'est-à-dire une sorte de table des matières, qui fera la correspondance entre une valeur d'index (ou clé) et l'adresse des données correspondantes.
Évidemment, les méthodes employées vont être définies par l'administrateur de la base en fonction des recherches qu'il souhaite accélérer, donc en fonction de recherches typiques, fréquemment utilisées, ou bien en fonction des jointures qui seront a priori faites sur la table considérée.

On ne peut optimiser globalement toutes les recherches possibles sur une table, mais on a toujours un ensemble de recherches types pour lesquelles une bonne organisation de la table apportera un gain de performances considérable.

IX 1-2 Les organisations structurées de tables Organiser une table selon une structure particulière signifie que les enregistrements qu'elle contient ne sont plus stockés en "tas" mais selon un ordre prédéfini.

Pour définir cet ordre, on va choisir, parmi les colonnes de la table, celles qui servent le plus souvent de critères de recherche et organiser la table par rapport à ces colonnes qui constitueront la "clé primaire" de la table.

Si par exemple on considère la table suivante :

personne (nom, prénom, date-naissance, ville, département)

Lorsqu'on cherche les personnes habitant une ville V donnée, avec une organisation en heap il faudra balayer séquentiellement toute la table personne pour trouver les réponses. 

Ceci peut être acceptable si la table est de petite taille, mais devient pénalisant avec des tables volumineuses, s'étendant sur un grand nombre de pages de disque.

Si la table est structurée sur une clé primaire "ville", on accélère la recherche d'une part parce que les personnes d'une même ville seront regroupées dans les mêmes pages, d'autre part parce que pour la valeur V de ville, l'organisation va donner l'adresse des personnes ayant cette valeur de ville.

Les organisations de tables qu'INGRES permet de créer sont les trois organisations classiques de fichiers :

  • le hachage (ou HASH) 
  • le séquentiel indexé (ou ISAM) 
  • l'arbre balancé (ou BTREE)
Chacune de ces organisations est fondée sur la définition d'une clé, formée par une ou plusieurs colonnes de la table.


IX 1-2-1 Principe du HASH Cette méthode consiste à associer à la clé une valeur entière, calculée par une fonction "de hachage", qui donnera une adresse, c'est-à-dire un numéro de page où se trouve l'enregistrement (ou les enregistrements) correspondant à cette clé.

Les enregistrements de la table d'origine sont stockés, après cette organisation, dans les pages correspondant à leur clé.

Si on reprend l'exemple précédent, une organisation de la table personne en hash sur la clé "ville" va restructurer la table de façon que toutes les personnes d'une même ville soient enregistrées dans la même page. 

Lorsqu'on recherche les personnes sur une valeur V de ville, la valeur de hachage correspondant à V donne le numéro de page où elles se trouvent. Dans ce cas, on a la réponse avec une seule entrée/sortie effectuée. 

Toutefois, il est possible que, pour une clé donnée, tous les enregistrements ne tiennent pas dans une seule page. On a alors des pages de débordement, chaînées à la première page pointée par la clé, ce qui pénalise la recherche.

L'organisation en hash est particulièrement bien adaptée à des recherches où le critère porte sur l'égalité de la clé primaire à une valeur donnée.

Il faut noter que le critère doit porter sur toute la clé pour tirer parti du hachage. Si la clé est formée de plusieurs colonnes, la recherche sur la valeur d'un sous-ensemble de ces colonnes ne présente plus d'intérêt.

De même, toute autre recherche, par exemple sur plage de valeurs telle que les personnes dont la ville commence par "PA", ne peut tirer profit de la clé de hachage.

Un autre inconvénient de la structure en hash est son encombrement, car les pages de données ne sont remplies par défaut qu'à 50%. Mais ceci peut être très facilement modifié et il est recommandé d'augmenter ce taux de remplissage pour des tables stables, rarement mises à jour.

schéma d'une structure hash :
 
 
 

clé1
 
clé2
...
clen
 

                                            ¯                                             ¯                                                 ¯
 

 page 1
 
page 2
 
page n
pages primaires de données

                                                                                            ¯                                                ¯
 

   
page i
 
page j
pages de débordement

                                                                                                                                              ¯
 

 page k


IX 1-2-2 Principe de l'ISAM L'organisation en ISAM consiste à créer un fichier indexé en :
  • triant les enregistrements sur la clé, 
  • créant un second fichier, fichier d'index, qui contient les couples (valeur de clé, adresse de page).
Une page pouvant contenir plusieurs enregistrements de clés différentes (mais triées), on ne stocke dans le fichier index qu'un nombre réduit de clés, une clé par page à adresser. On dit que l'on a un index "non dense".

Dans INGRES, l'index est géré par deux niveaux : la racine et les pages d'index; une page d'index contient les clés maximales de chaque page de données, avec leur adresse; la racine pointe elle-même les pages d'index selon leur clé maximale.

schéma de l'ISAM :
 

cléi
..........
clén
racine

                                                                                             ¯                                       ¯ 
 

 cléd
.......
cléi
 
clék
.......
clén
pages d'index

                                           ¯                                             ¯                                         ¯                                            ¯
 

 page 1
 
page 2
 
page 6 
 
page n
pages primaires de données

                                        ¯                                                                                          ¯
 

 page i
     
page j
   
pages de débordement

                                                                                                                                 ¯
 

 page k

Cette organisation est très bien adaptée aux recherches sur valeur exacte de la clé, ou sur plage de valeurs, ou sur la valeur de la partie gauche de la clé quand elle est formée de plusieurs colonnes, puisque les enregistrements sont triés sur la clé.

Son inconvénient majeur est la difficulté des mises à jour et les effets de débordement qu'elles peuvent produire : les nouveaux enregistrements doivent être placés dans les pages pointées par leur index et, quand une page est pleine on crée une page de débordement. 

On peut ainsi, après avoir fait des insertions massives dans la table, avoir à parcourir un grand nombre de pages pour trouver les données.

Il faut, pour éviter cela, réorganiser souvent la table.


IX 1-2-3 Principe du Btree Le Btree, ou arbre balancé, est une organisation de fichier de type indexée où le fichier d'index est lui-même indexé : les clés du fichier d'index sont gérées par un deuxième niveau d'index, et ainsi de suite...jusqu'à arriver à un niveau d'index où toutes les clés tiennent dans une seule page.

On constitue ainsi, avec les différents niveaux d'index, un arbre d'index. Cet arbre est dit balancé car tous les noeuds terminaux (ou feuilles) sont au même niveau.

Les noeuds terminaux pointent sur les pages de données, tandis que les noeuds intermédiaires pointent sur les pages d'index du niveau inférieur.

Au départ, lorsque la table est structurée en Btree, les données sont triées. Ensuite, les données insérées sont stockées dans les pages suivantes, sans avoir à les réorganiser : seuls les index vont être réorganisés dynamiquement.

Cette propriété du Btree utilisé dans INGRES tient dans le fait que les noeuds terminaux contiennent toutes les clés des données de la table : on dit que l'index est "dense".

Donc, la table peut grossir sans qu'il y ait de problèmes de débordements comme en ISAM, mais en contre partie, le fichier d'index sera grand et grossira en même temps que la table.

L'exemple suivant illustre un Btree d'une table personne dont la clé est le nom.
 

racine

<= MacShane >

 

les clés <= MacShane sont pointées par la branche gauche, les autres par la branche droite

                                                                ¯                                          ¯
 

 clé page feuille

Giller 1

MacShane 2

  clé page feuille

Shigio 3

ZZZZ 4

index niveau 1

feuilles
 

page feuille 1   page feuille 2   page feuille 3   page feuille 4
adresse

Blumb 1,1

Brodie 1,3

Charles 1,2

Curry 2,0

...

Giller 2,3

  adresse

Green 3,3

Huber 3,2

...

...

...

MacShane 4,3

  adresse

Ming 5,1

...

...

...

...

Shigio 6,3

  adresse

Stan 7,1

...

...

...

...

Zimmer 8,1

Les adresses donnent la page de la donnée et son emplacement dans la page.

Cette organisation est bien adaptée à la recherche sur une plage de valeurs de la clé, sur la partie gauche de la clé, ainsi que sur sa valeur exacte.

Elle pose moins de problèmes que l'ISAM si on a beaucoup de mises à jour ou d'insertions à faire.

Mais elle prend beaucoup de place pour gérer les index (dans les feuilles, on a un index dense).


IX 1-3 Commande pour organiser une table La commande pour organiser une table est la commande modify : modify table to structure [on col1 {,col2 ...}][with clause] exemples :

organiser la table personne en hash sur les colonnes "nom", "prénom" :

modify personne to hash on nom, prénom; Si on ne met pas l'option "on col1, col2..", la première colonne va être prise pour former la clé.

organiser la table personne en isam sur la colonne "ville" :

modify personne to isam on ville; remarque : on ne peut pas avoir deux structures différentes, sur deux clés différentes, de la même table.

organiser la table personne en btree sur la colonne "departement" :

modify personne to btree on departement; Réorganisation d'une table en heap : celle-ci est souhaitable si la table doit rester en heap, après lui avoir fait des mises à jour, car elle permet de récupérer la place des suppressions, de supprimer les doubles. 

Elle peut aussi être faite avec un tri, par la structure "heapsort" au lieu de heap, ce qui permettra de remettre les données dans un ordre trié (mais sans clé d'accès) sur le disque. Ceci est intéressant si on a, par ailleurs, un accès par clé secondaire (voir plus loin) car les données accédées seront regroupées.

exemple : réorganisation en heapsort de la table personne, sur le nom :

modify personne to heapsort on nom; par défaut le tri est ascendant, on peut demander un tri descendant : modify personne to heapsort on nom desc; Remarque : quand on supprime toutes les données d'une table, par exemple par un ordre "delete from nom_table", la place sur disque n'est pas récupérée; pour supprimer toutes les données d'une table et récupérer la place sur disque, lancer la commande : modify nom_table to truncated; La table est réorganisée en heap.

D'autres options de la commande modify permettent de régler le remplissage des pages, les nombres de pages index, etc..., mais les paramètres par défaut sont généralement suffisants. On peut, pour limiter le nombre de pages à lire, remplir à 100 % une table ne subissant pas de modifications :

modify nom_table to isam with fillfactor = 100; On peut également, en réorganisant une table, demander la "compression" des données et/ou des clés, avec la clause : with compression [= ( key | data )] ; On gagne de la place sur les colonnes en varchar mais la décompression prend un temps supplémentaire à l'extraction des données; ce n'est conseillé que pour des tables stables (parfait pour les libellés documentaires). IX 1-4 Conseils pour l'organisation des tables
  • on a intérêt à créer et charger les tables en heap pour les organiser par la suite, en fonction des requêtes et des jointures les plus fréquentes à faire;
  • après modification sur une organisation, il faut vérifier par "help table nom_table" que le nombre de pages de débordement n'est pas trop grand. Sinon, il faut choisir une clé plus sélective;
  • une organisation en ISAM est généralement la plus avantageuse, pour des recherches sur valeurs exactes ou plages de valeurs; elle devient pénalisante en cas de mises à jour importantes et il faut alors réorganiser la table;
  • l'organisation en HASH convient surtout aux recherches sur valeurs exactes, à condition d'utiliser toute la clé; elle doit être refaite en cas de mises à jour importantes;
  • l'organisation en BTREE est bonne pour les recherches sur valeurs exactes ou plages de valeurs et, surtout, elle est intéressante en cas de mises à jour importantes quand il est difficile d'arrêter l'exploitation pour réorganiser la table;
c'est une organisation conseillée uniquement quand les autres ne sont pas envisageables !
  • pour des petites tables, l'organisation HEAP ou HEAPSORT peut convenir; il est bon de la refaire après mises à jour;
  • pour des tables assez volumineuses, souvent consultées ou souvent jointes avec d'autres, le choix d'une clé et d'une organisation de la table sur cette clé s'impose pour gagner énormément en performances.

IX 1-5 Utilisation des index secondaires L'organisation d'une table selon une clé primaire crée un chemin d'accès privilégié sur cette table.

Mais il arrive fréquemment que l'on ait besoin d'accélérer les accès à une table sur d'autres colonnes que sur la clé primaire. Par exemple, on a pris "ville" comme clé primaire de la table personne parce que l'on a souvent à faire une jointure sur les villes, mais si on a à chercher les personnes sur date-naissance, notre clé ne sert plus.

On peut utiliser un deuxième type d'accès privilégié, soit seul, soit combiné avec une structure de table : c'est la création d'un index secondaire.

Cet index secondaire consiste à créer un fichier d'index sur une clé "secondaire", formée par une ou plusieurs colonnes de la table, sans réorganisation des données : le fichier d'index va donner, pour chaque clé secondaire, l'adresse de l'enregistrement correspondant à cette clé.

Le fichier d'index est traité par INGRES comme une table qui contient, au lieu des données, des couples (clé, adresse de donnée).

Il est créé par la commande :

create index inom on nom_table(col1 {,col2})[with structure = structure]  exemple :  create index idatnais on personne (date_naissance); Le fichier d'index étant géré comme une table, on peut lui donner une structure. Par défaut, sa structure est de type ISAM. Et c'est généralement satisfaisant. Mais on peut, pour des problèmes de mises à jour fréquentes, lui donner une autre structure, par exemple BTREE.

Remarque : une clé secondaire peut être formée de colonnes faisant partie de la clé primaire.

IX 1-6 Critères de choix d'une clé ou d'un index Une bonne clé (un bon index) doit être :
  • unique ou très discriminante (peu ou pas de doublons) 
  • courte (en caractères et colonnes) 
  • de type simple (le mieux : entier) 
  • non sujette à calcul ou mise à jour
Il ne faut pas créer trop d'index, surtout si la table est très dynamique.

Que prendre comme clé ?

  • l'identifiant logique des enregistrements de la table 
  • à défaut, une clé de substitution, c'est à dire une clé interne qui peut être naturelle (n° SS, code ...) ou artificielle (aléatoire...)
Par exemple, si on a la table foyer avec les colonnes "nom" et "details", où nom est l'identifiant logique, il peut être nécessaire, à cause des noms synonymes, de prendre une clé de substitution : le code INSEE pourrait jouer ce rôle.

Ingres, depuis la version 6.4, permet de créer automatiquement une clé unique qui sera mise à jour par le système à chaque nouvelle insertion de tuple.

Cette possibilité est offerte dans la commande de création de table.

exemple :

create table foyer (

ident table_key with system_maintained,

nom char(30),

details char(100) );

Une autre solution efficace est possible, en utilisant les règles et procédures (voir le chapitre SQL).

Lorsqu'on traite des données hiérarchisées, on a des clés "en cascade", par exemple du type code_pays, code_region, code_ville.

Supposons que ces codes soient numériques et représentés par idpays, idregion et idville :

pays (idpays,..

region (idpays, idregion,...

ville (idpays, idregion, idville,..

Pour trouver 2 villes de la même région, on a 2 tests à faire, sur idpays et idregion :

...

where v1.idpays = v2.idpays

and v1.idregion = v2.idregion;

Pour accélérer les recherches, on peut créer des clés agrégées, par exemple remplacer idpays et idregion par idpaysreg où :

idpaysreg = idpays * 100 + idregion 

La recherche précédente peut alors se faire avec un seul test :

where v1.idpaysreg = v2.idpaysreg; IX 1-7 Conclusion : choix d'une structure de stockage La structure ISAM est généralement un bon compromis, surtout si on effectue régulièrement des réorganisations; toutefois voici quelques cas particuliers et la structure alors conseillée :
 
 

UTILISATION DES TABLES

 

 

STRUCTURE CONSEILLÉE

 

 lecture seulement
ISAM ou HASH
 écriture massive
HEAP
 mises à jour nombreuses
ISAM avec réorganisation fréquente
 recherches sur : intervalles
ISAM, BTREE
 recherches sur : valeurs exactes
HASH
 utilisée 24h/24
BTREE

On peut également conseiller la structure HEAP pour une table très petite (moins de 5 pages) ou HEAP avec des index secondaires pour une table très grosse (plus de 2000 pages)


IX 2 Optimisation des performances

IX 2-1 Statistiques

Ingres possède un optimiseur de requête qui analyse la requête SQL et établit un plan d'exécution optimal (Query Execution Plan ou QEP) pour minimiser le temps de traitement. Cet optimiseur travaille d'après des informations statistiques sur les tables et les valeurs des colonnes.

Ces informations peuvent être estimées par l'optimiseur ou générées par un utilitaire "optimizedb" qui fournit des statistiques : valeurs uniques et histogrammes de valeurs des colonnes.

Pour obtenir des plans d'exécution corrects, on a intérêt à fournir à l'optimiseur des statistiques à jour, en lançant, au niveau UNIX, la commande :

$ optimizedb [options] nom_base -rnom_table -anom_col exemple (avec base parcauto) : lister les véhicule construits avant 81 dans les foyers dont le chef de famille gagne plus de 90000F : ... where f.ident = v.ident

and v.ancstr <81 and f.revenu > 90000

On suppose que les tables sont indexées sur ancstr et revenu.

Pour choisir quel index utiliser en premier, l'optimiseur va utiliser les statistiques fournies par optimizedb :

$ optimizedb parcauto -rfoyer -aancstr -arevenu (cette commande demande des statistiques sur les colonnes ancstr et revenu de la table foyer)

ou bien :

$ optimizedb -zk parcauto (cette commande demande des statistiques sur toutes les colonnes "clés" de la base)

L'idéal est de lancer optimizedb non seulement sur les clés principales ou secondaires, mais aussi sur toutes les colonnes référencées par les clauses where.

Il faut éviter de lancer la commande optimizedb sur toutes les colonnes de toutes les tables de la base, en faisant : optimizedb nom_base , car la création de toutes les statistiques est extrêmement longue et inutile. 

Après chaque passage de la première commande "optimizedb", il est conseillé de lancer la commande Unix "sysmod" qui réorganise les tables systèmes :

$ sysmod nom_base  La commande optimizedb doit être réexécutée après des mises à jour importantes de la base.

Si certaines statistiques sont devenues inutiles, on peut les détruire avec la commande Unix

$ statdump -zdl nom_base [-rnom_table -anom_col] Attention !! lancer cette commande avant optimizedb plutôt qu'après, une erreur risquant de détruire les statistiques récentes.


IX 2-2 Conseils pour écrire ses requêtes SQL offre la possibilité d'écrire une même requête de plusieurs manières et il est important de respecter certaines règles donnant la meilleure performance.

Par exemple, pour obtenir l'ensemble des foyers ayant au moins un véhicule, on peut écrire 3 formes de requêtes :

1ère requête (jointure simple) :

select distinct f.ident 

from foyer f, vehicule v 

where f.ident = v.ident;

2ème requête (subquery) : select distinct f.ident 

from foyer f

where exists

(select * from vehicule v where f.ident = v.ident); 

3ème requête (subquery) : select distinct f.ident 

from foyer f

where f.ident in

(select v.ident from vehicule v); 

la première requête est préférable aux deux autres car elle utilise une jointure simple, plus rapide à exécuter que les "subquery" faisant appel à "exists" ou "in".

En général, l'utilisation des formes exists ou in pourrait être évitée par l'usage d'une "jointure externe", c'est-à-dire une jointure entre 2 tables où on garde à la fois les lignes répondant au critère de jointure et les lignes de la 2ème table ne répondant pas au critère. 

On peut donc éviter la forme exists ou in en réalisant une jointure externe avant la sélection.

Exemple : on veut trouver les foyers n'ayant pas de véhicule.

La requête avec exists s'écrit :

select f.ident from foyer f

where not exists

(select * from vehicule v where f.ident = v.ident);

Une autre façon d'écrire cette requête est de passer par une table temporaire "temp" dans laquelle on va créer le résultat d'une jointure externe entre foyer et véhicule foyer
 
 
 

f1

ident
 
 

 

 
 
 

 

 
 
 

 

 
 
 

 

 

f2

 

 

 

 

 

 

 

 

vehicule
 
 
 

v1

ident
 
 

 

 
 
 

 

 
 
 

 

 
 
 

v2

 
 
 

 

 
 
 

 

 
 
 

 

Dans la table foyer, les foyers f1 ont au moins un véhicule, ce qui correspond à l'ensemble des véhicules v1.

Les foyers f2 n'ont pas de véhicule; on cherche cet ensemble de foyers.

Les véhicules v2 ne correspondent à aucun foyer de la table foyer.

Faire une jointure externe gauche entre foyer et vehicule consiste à prendre tous les 'ident' de foyer et de vehicule, existant dans au moins une de ces 2 tables :

create table temp as 

select f.ident, v.ident as vehic

from foyer f left join vehicule v on f.ident = v.ident; 

temp

 
 
 
 

f1

ident
 
 

 

vehic
 
 

 

 

f2

 

NULL

Pour trouver les foyers correspondant à l'ensemble f2 :

select ident from temp where vehic is NULL; Cette deuxième écriture est beaucoup plus performante que la première et elle est très intéressante, surtout si les deux tables sont volumineuses.


IX 2-3 Règles de performances
  • Utiliser une jointure simple de préférence à une subquery. 
  • Remplacer not in par not exists qui est un peu moins long. 
  • Remplacer de même in, any et all par exists, mais surtout, chercher à s'en passer (voir exemple précédent).
  • Simplifier les expressions dans les critères de sélection :
ainsi préférer la fonction like aux fonctions right et left : where left(depcom,2) = '78' mieux : where depcom like '78%'
  • éviter les requêtes 'or' complexes; elles génèrent un produit cartésien, que l'optimiseur ne peut pas toujours gérer (débordement de mémoire);
exemple : on a la table voiture(ident, an, couleur) et la requête : where (couleur = 'vert' and an = 83)

or (couleur = 'bleu' and an = 73)

or (couleur = 'jaune' and an = 88)

or ....

mieux : passer la requête en plusieurs fois, ou, encore mieux : créer une table temporaire : create table temp (couleur varchar(10), an integer2); 

insert into temp values('vert',83);

.......................('bleu',73); 

..................... ('jaune',88); 

.....

et faire la jointure : where v.couleur = temp.couleur and v.an = temp.an exemple : trouver les foyers dont le chef de famille est né avant 1940 ou ayant au moins un véhicule : where f.cnaiss <40 or f.ident = v.ident  mieux (si on a des clés, index ou statistiques sur cnaiss et ident) : select ident from foyer f

where f.cnaiss < 40

union

select ident from foyer f, vehicule v

where f.ident = v.ident;

Agrégats

moyenne des âges de parents et d'enfants :

create table temp as

select age from parent ; 

insert into temp

select age from enfant ; 

select avg(age) from temp ; 

mieux, si beaucoup de parents et enfants : create table temp as select

count(*) as nombre,

sum(age) as somme 

from enfant

insert into temp

count(*), sum(age) from parent

select float4 (sum(somme)) / sum(nombre) as moyage 

from temp

Éviter de faire order by sur des résultats déjà triés par group by : select cprof, sum(revenu) as trevenu

from foyer

group by cprof

order by cprof

ici order by est inutile


IX 2-4 Règles de vie - concurrence But : éviter de se bloquer entre usagers Ingres en général, ou entre usagers d'une même table ou même un usager tout seul !

En effet, le fichier logfile, qui garde les résultats de toutes les sessions en cours, est partagé par tous les usagers Ingres.

Avec SQL

  • pour les débuts, ne pas lancer vos requêtes avec COMPLETE mais avec GO, on peut ainsi s'apercevoir d'une erreur dès le premier écran résultat et corriger; 
  • tester vos requêtes sur de petites tables; 
  • apprendre à optimiser les requêtes; 
  • détruire régulièrement les tables temporaires de travail;
(détruire toutes les lignes d'une table par : modify nom_table to truncated) Avec QBF, REPORT ...

Utiliser l'appel direct plutôt que par ingmenu.

Ces outils écrans sont gros consommateurs de balayage de table : essayer de limiter et écourter leur emploi.

Lors d'insertions ou mises à jour fréquentes, revenir à l'écran des fonctions QBF (idem lors d'une interruption ...).

Éviter d'utiliser TableField ou des jointures trop grosses, utiliser des vues ou des tables temporaires pour restreindre l'information fournie au minimum utile.

Problème d'interblocage lors de mises à jour :

Des usagers simultanés de la même table peuvent se bloquer. Si cela arrive trop fréquemment, revoir la structure de la table.

HEAP est à changer en HASH ou en BTREE, qui doit donner de bons résultats. 

Dans ce cas, penser aussi à réduire aussi les facteurs de remplissage de la table ET des index secondaires.

Si trop de problèmes en interactif :

avant de passer à des requêtes en applicatif, différer vos requêtes en "heures creuses" grâce à l'outil ingnuit (voir cours outils Ingres) 


IX 2-5 Mises à jour et réorganisations Les tables subissant des mises à jour importantes doivent être réorganisées, c'est indispensable pour maintenir des performances convenables.
  • refaire modify pour retrier les données et récupérer l'espace (même en gardant une structure identique) 
  • recréer les index (détruits par modify) 
  • passer (au niveau unix) les commandes :
$ sysmod nom_base [table1 {,table2}]

(réorganise les tables système Ingres)

et, également, de temps à autre :

$ verifydb -mruninteractive -sdbname "nom_base" -opurge

qui élimine les informations périmées.


IX 3 Résumé des actions à entreprendre pour maintenir de bonnes performances

IX 3-1 Actions sur les tables

  • au niveau du schéma : avoir un identificateur court, sur une seule colonne, de type entier si possible. 
  • pour le chargement en masse de données : garder (ou revenir à) l'organisation heap
modify nom_table to heap ; 
  • pour toutes les tables stables ayant entre 20 et 2000 pages (help table nom_table vous donnera le renseignement), choisir l'organisation isam et : 
  • si la première colonne du schéma est la partie la plus importante de l'identifiant :
modify nom_table to isam with fillfactor = 90 ; 
  • si plusieurs colonnes interviennent fréquemment dans le where:
modify nom_table to isam on col1 {, col2} with fillfactor=90 IX 3-2 Créer les index  sur les colonnes fréquemment présentes dans le where : create [unique] index n_index on nom_table (col1 {, col2})

IX 3-3 Créer (mettre à jour) des statistiques

c'est une commande au niveau Unix, à faire au minimum sur les clés : $ optimizedb -zk nom_base pour les autres colonnes (et seulement celles qui apparaissent dans le where) : $ optimizedb nom_base -rnom_table -acol1 {-acol2} si trop de statistiques sont devenues inutiles : $ statdump -zdl nom_base [{-rnom_table {-acolj}]

IX 3-4 Réorganiser les tables système

Chaque ordre sql drop, ou commande optimizedb relancée, encombre les tables système de données inaccessibles (tables détruites par exemple), il faut nettoyer ces tables de temps en temps par : $ sysmod nom_base une autre commande Unix permet de nettoyer des fichiers devenus inutiles : $ verifydb -mruninteractive -sdbname "nom_base" -opurge

IX 3-5 Nettoyer la base elle-même

Ne pas oublier de détruire les tables résultats, surtout si elles ne sont pas renseignées : une information, sans aucun renseignement sur son obtention, n'a aucune fiabilité. IX 3-6 Tester les requêtes éventuellement sur des tables de taille réduite avant de les exécuter en vraie grandeur