Requêtes et performances

Ce cours manipule des concepts comme les sous-systèmes et les pools mémoire qui doivent vous être familiers, si ce n'est pas le cas, voyez cette introduction

Préalable

    1. CQE, le plus ancien
    2. SQE arrivé en 5.2, implémenté au niveau microcode
    3. les deux cohabitent, il y a donc une couche logicielle, le query dispatcher qui décide, pour une requête, qui va faire le job
      (si SQE sait faire, c'est lui qui va être invoqué, sinon, à défaut CQE)
    4. SQE évolue (et donc sait traiter de plus en plus de cas) au fur et à mesure des versions et des PTF.


I/ Les leviers à notre disposition

 les préconisations matérielles d'IBM pour les bases décisionnelles, sont les suivantes :

Le système garde en mémoire de nombreuses informations liées à la base de données :

D'un point de vue base de données, il faut éviter les IPL trop fréquent qui risque d'engendrer le syndrome "Lundi matin" quant aux temps de réponse.

  Les recommandations sont claires : IPL mensuel voire trimestriel,

vous en profiterez pour appliquer les derniers groupes PTF, particulièrement le DATABASE GROUP qu'il faut suivre régulièrement sur
http://www-01.ibm.com/support/docview.wss?uid=nas8N1021657

 

L'optimiseur prend des décisions en fonction de la mémoire disponible, tout en essayant de laisser de la mémoire aux autres travaux (fair share)

CQE  effectue un calcul simple : "taille du pool/ niveau d'activité" = mémoire maxi par job.


Si votre requête s'exécute seule dans un pool (ce qui est conseillé) , descendez le niveau d'activité à 1.



»Pour travailler dans un Pool dédié :


allouez de la mémoire à un Pool partageable : CHGSHRPOOL *SHRPOOLn SIZE(xxx)

créez un sous système utilisant ce pool :

CRTSBSD MONSBS POOLS((1 *SHRPOOL1)) TEXT('Sous système dédié')
puis
ADDRTGE MONSBS SEQNBR(10) CMPVAL(*ANY) PGM(QCMD) CLS(QBATCH)    

                      


» En même temps, utilisez l'expert cache qui est toujours une bonne solution pour les accès base de données, dans des pools mémoire de plus de 100 Mo
(on garde en mémoire les tables les plus utilisées).

Cela se paramètre par CHGSHRPOOL PAGING(*CALC)

SQE, lui divise la taille du pool par le nombre moyen de travaux
    (expert cache obligatoire, pour faire la moyenne)

ATTENTION, Si vous faites des tests, le deuxième test ira toujours plus vite que le premier, du fait que les données sont (partiellement ?) restées en mémoire, ce qui peut fausser vos mesures.

Placez vous alors Obligatoirement dans un pool ou vous êtes seul, et lancez entre deux requêtes :

CLRPOOL POOL(*SHRPOOL1)

-> Pour garder les données complètement en mémoire pour pouvez utiliser la commande SETOBJACC ou bien la nouvelle fonctionnalité de la version 7 :

 

 

- Le pool mémoire utilisé est celui indiqué par MEMORY_POOL_PREFERENCE du fichier QAQQINI, qui doit être à *CALC :

 

- Le fichier est monté en mémoire "à la demande" (lors de la première requête) en mode asynchrone et en parallèle
 (contrairement à SETOBJACC qui n'utilisait qu'un seul thread)

 

- La conservation complète du fichier n'est pas garantie, mais si vous avez de la mémoire elle est fort probable


Pour visualiser la mémoire consommée par SQL, Regardez SYSTMPSTG (Bucket *DATABASE...)


Ce paramètre est renseignable sur les commandes STRSQL , RUNSQLSTM


- *NO la copie des données n'est pas admises (pour des besoins de temps réel)

- *YES la copie des données est admise, elle n'a lieu que quand il est impossible de faire autrement

- *OPTIMIZE la copie des données est admise, elle aura lieu à chaque fois que cela améliorera les temps de réponses
(particulièrement le hachage pour les jointures et les index bitmap)


c'est cette dernière valeur qu'il faut privilégier (elle est par défaut via ODBC./JDBC).


Vous pouvez influencer l'optimiseur de requêtes en indiquant le nombre de lignes à traiter en même temps :


Si vous indiquez une petite valeur, l'optimiseur cherche à rendre un résultat le plus rapide possible, vous le forcer à utiliser des index, même si le temps global doit en pâtir.
C'est une solution interactive (STRSQL considère, sans indication de votre part, une optimisation pour 3% des lignes du fichier)

Si vous indiquez une GRANDE valeur (FOR ALL ROWS est admis depuis V4R30) l'optimiseur privilégie le temps global de traitement. Vous favoriserez les copies temporaires, les tris, le hachage s'ils sont plus efficaces)

C'est une solution purement orientée batch et gros volumes.
(INSERT into …SELECT … FORM …, est toujours traité pour un nombre maxi de lignes)


 


II/ Les outils de mesure :

a/ Commandes système


WRKSYSSTS (gestion de la mémoire)


ATTENTION, tous ces écrans vous offrent des moyennes, il faut visualiser des données qui ont au moins 2 minutes .


la documentation V5R40 indique comme base de calcul rapide, par pool (ligne) :

c*p, où
  c
est le pourcentage de CPU utilisé
  p est le nombre de processeurs de la partition

par exemple

1 processeur à 36 % = 36 de taux de pagination maxi
1,8 processeur (LPAR) utilisé à 80% = 144

C'est aussi cet écran (par F11) qui permet de fixer l'expert cache.


WRKDSKSTS (gestion des disques)

 

cet écran montre le taux d'occupation des disques (l'idéal est un taux de 75 % au maximum)
ainsi que l'activité des bras (% util).Une activité au delà de 50% indique des disques très occupés.

si la répartition n'est pas linéaire (achat de nouveaux disques, par exemple), passez la commande STRASPBAL TYPE(*CAPACITY)

 

b/ Base de données

D'abord un petit, "truc", mettez le paramètre QRYTIMLMT à 0 par la commande CHGQRYA :

toutes vos requêtes seront alors refusées (CPA4259) , l'optimiseur vous indiquant le temps qu'il a prévu.


1/ En interactif, passez la commande STRDBG avant de lancer SQL en mode 5250 ,

vous verrez alors après chaque requête des messages CPI43xx ainsi que SQL79xx dans l'historique indiquant les choix de l'optimiseur lors de la création du plan d'accès


2/ pour un programme, vous pouvez voir le plan d'accès par la commande PRTSQLINF

vous verrez alors, dans un spool portant le nom du pgm, pour chaque requête des messages SQL40xx

 

3/ Pour les Batch, utilisez le Moniteur base de données :


dans une session 5250, lancez la commande STRDBMON

rappel, utilisez les paramètres suivants

-  RUNTHLD : seuil en secondes, de temps d'exécution
-  STGTHLD : seuil en Mo de mémoire utilisée
-  FTRFILE : filtrage du moniteur sur un nom de fichier
-  FTRUSER : filtrage du moniteur sur un profil utilisateur
-  FTRINTNETA : filtrage du moniteur sur une adresse IP cliente
-  FTRQRYGOVR : filtrage du moniteur sur l'annulation de la demande pour dépassement de critère donné par CHGQRYA

    -> pour analyser ensuite le résultat, IBM propose la création de vues voir https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/rzajq/lofdds.htm


    ou mieux,
    via ACS (voir ci-dessous) : Utilisez "Performance Center"


Les outils graphiques

1/ le gestionnaire de scripts SQL

Vous pouvez :


une option ALLOW SAVE RESULT, permet la sauvegarde des enregistrements extraits:

ensuite, avec un clic droit sur les lignes affichées :


Les formats admis, sont :

Plusieurs paramètrages de la connexion (JDBC) peuvent être mémorisés





Vous choisissez ensuite comme ceci :



Vous avez accès aux travaux et à la dernière requête SQL pour chacun d'eux (Affichage/SQL details for a Job)


Enfin, la(les) requêtes(s) peuvent être sauvegardée(s) (uniquement en local)

2/ le moniteur de perf. Base de données.

Depuis performance center, choisissez l'option Nouveau...

cliquez sur moniteur de Base de données / nouveau ...




remarquez :


   Choix des travaux


   et récapitulatif final.

 

Quand la trace est terminée (l'arrêt est à votre charge), choisissez une vue (les données à afficher)




Avec un classement par catégorie




, ci-dessous par opération :



Vous pouvez aussi utiliser IBM Navigator for I (Performances/Etude des données) :

Mais surtout, nous avons maintenant des statistiques d'Entrée/Sortie globales (sous PDI)



Choisissez la bibliothèque et la collecte (ou laissez "la plus récente")

Entrée/sortie base de donnée physiques, vue détaillée


Par travail :


Par sous-système


Par type de serveur

 

3/ Cache des Plans d'accès


Le jeu d'instructions actuellement en cache pouvant être sauvegardé sous forme d'image (snapshot).
(sinon, il y a mise à blanc à l'IPL)

4/ Analyse des statistiques et des Index


Pour définir ou voir les statistiques, Utilisez la nouvelle (1.1.7) option Schémas


Include permet de choisir les bibliothèques à afficher




Toutes les listes peuvent être sauvegardées

   

Vous avez le choix des colonnes à l'affichage

• Liste des tables


ET depuis la 1.1.7.1, l possibilité de filtrer



Sur une table, option "Satistic Data"

Vous montre les statistiques réalisées



 

Vous pouvez retrouver les sources de ces procédures via System i Navigator ou ACS (elles sont livrées "tel que") et les personnaliser.

4/ Visual Explain

 

Vous pouvez maintenant obtenir une Explication graphique du détail d'une requête SQL avec Visual Explain :

 

Visual Explain peut être lancé et réactualisé, pendant l'exécution, les informations ayant bougé sont surlignées.

 

 

 

 

 

Visual Explain vous affiche alors le détail des différentes phases de la requête :

A partir de cette requête


•Scannage de table et/ou utilisation d'un index

• phase de jointure

 

ici en utilisant des index pour la jointure
et avec agrégation (pour count(*) )



Le résultat étant stocké dans une liste temporaire

• pour terminer, lecture de la liste temporaire et production du résultat


La fenêtre droite vous donne le détail pour chaque étape


ici, le résultat final indiquant le moteur utilisé

ici la phase jointure

Les messages de l'optimiseur (précisant la jointure)
étant affichés dans cet onglet

depuis la 6.1, SQE possède un module d'auto-apprentissage, qui agit aujourd'hui dans 2 cas :

Rappel :

 

· Les informations affichées par Visual Explain

Chaque icône représente une action :

les actions peuvent être enchaînées : accès direct à un index (SETLL), puis balayage (READE)

Ces actions vont porter sur un/des objet(s) :
Icône STRDBG PRTSQLINF Commentaires
Table Scan
Table Scan
CPI4329 SQL4010 Utilisé pour retourner un grand nombre de lignes
Table Probe
Table Probe
 
Accès direct à une ligne par son n° de rang
(la connaissance du n° de rang peut venir d'une lecture d'index)
Index Scan
Index Scan
CPI4328 SQL4008
utilisé pour retourner un petit nombre de lignes, si l'index correspond au critère de tri ET à une sélection, par exemple.
Index Probe
Index Probe
CPI4338 SQL4032
utilisé pour retourner un petit nombre de lignes, l'index permettant de réaliser la sélection la plus importante
(primary key, par exemple)

Index Probe
EVI Probe
CPI4328 SQL4008
SQL4011
utilisé éventuellement avec d'autres pour créer un bitmap, entraîne ensuite un accès direct sur la table (table probe)
Icône STRDBG PRTSQLINF Commentaires
Hash Scan
Hash Scan
CPI4329 SQL4010
SQL4029
Utilisé  principalement pour la gestion du GROUP BY
Table Probe
HASH Probe
CPI4327 SQL4007
SQL4011
Utilisé principalement pour la jointure
Temporary Sort List
Liste triée (Scan)
CPI4328
CPI4325
SQL4008
SQL4002
Utilisé  pour Order BY et l'option DISTINCT
Temporaty List Probe
Liste triée (Probe)
CPI4327 SQL4007
SQL4010
Utilisé pour une jointure avec un autre critère que l'égalité
Temporary List
Liste simple (Scan)
CPI4325
CPI4327
SQL4007
SQL4010
Utilisé pour préparer une utilisation parallèle (SMP)
Temporaty Row Scan
Liste numérotée (Scan)



Utilisé avec des index multiples pour favoriser ensuite le groupage des I/O disque.  (récupération physique des lignes par paquet)
Temporaty Row Probe
Liste numérotée
(Accès direct)
 CPI4338  SQL4032 technique bitmap pour combiner plusieurs index et limiter ensuite l'accès direct aux lignes de la table
Bitmap Scan
Bitmap Scan
 CPI4338  
SQL4010
SQL4032
technique pour combiner plusieurs index en un index bitmap.

Un index bitmap est un nuage de point ou chaque position représente l'adresse, un liste numérotée contient les adresses (N° de rang)
Bitmap Probe
Accès direct Bitmap
 CPI4338 SQL4011
SQL4032
technique bitmap pour combiner plusieurs index et limiter ensuite l'accès direct aux lignes de la table
Index Scan
Index Scan
CPI4321 SQL4009
Utilisation d'un index temporaire pour tri ou groupage  (MTI)
Index Probe
Index Probe
CPI4321 SQL4009
Utilisation d'un index temporaire, probablement pour jointure
BUffer Scan CPI4330 SQL4030 Objet temporaire utilisé lors des opérations de parallélisme (SMP)

 

 

 


Enfin, l'icône vous donnera des informations globales (temps, nombre de lignes résultat , ...)

Nouveaux en V5R40

Index Probe
EVi table Scan, preload
CPI4328 SQL4008
utiliser pour retrouver les entrées à partir uniquement de la table des symboles d'un index EVI
    BUffer Scan
    QUEUE/DEQUEUE
(pas de message) (pas de message) QUEUE, Objet temporaire pour mémoriser des données durant une requête récursive


Nouveaux en V6R10

Index Probe
temporary distinct Sorted list Scan
(pas de message) (pas de message) Liste triée de valeurs distinctes, utilisée pour GROUP BY ROLLUP
              BUffer Scan
    temporary value List Scan
CPI4329
Arrival sequence
was used for file *VALUES
SQL4010 Liste de valeurs temporaires, utilisée avec VALUES( )


Nouveaux en V7 (les index EVI peuvent maintenant être utilisés en lecture pour GROUP BY et DISTINCT)

Index Probe
EVI Table SCAN, preload
CPI4328
SQL4008 Lecture d'un Index EVI avec INCLUDE pour fonction d'agrégation (GROUP BY)
             BUffer Scan
    EVI Table Probe, Preload
CPI4328
SQL4008 Lecture d'un Index EVI avec INCLUDE pour fonction d'agrégation (GROUP BY et WHERE)
             BUffer Scan
          UNNEST ARRAY
CPI4329
SQL4010 Utilisation de la fonction UNNEST d'un tableau SQL (ARRAY) dans une procédure
             BUffer Scan
          EVI Only Access
CPI4338
  Utilisation de deux index EVI, l'un pour la sélection, l'autre pour les colonnes à afficher (la table n'est pas lue, voir ce cours)

Visual Explain sait pleinement tirer profit des différentes évolutions, comme la collecte de statistiques.

 

le Menu Option propose

• Vous retrouverez ces informations depuis un moniteur


de fait quand on lance Visual Explain



 

Quelques recommandations

 

  • Respectez bien les trois formes normales (voir Wikipedia s'il le faut)
  • Ayez un dictionnaire de données afin qu'une information soit toujours codée de manière identique

          ÉVITEZ ABSOLUMENT :
             - le n° de client packé dans un fichier, étendu dans l'autre
             - date dans un fichier et jour/mois/année dans l'autre
  • n'indexez que l'essentiel, un index c'est aussi des cycles CPU consommées lors des écritures,mises à jour.
    (faites la chasse aux index non utilisés en filtrant, comme vu plus haut)
  •   SÉLECTION  

     il faut bien voir que le but est de gagner du temps. Or ce qui prend le   de temps, ce sont le E/S (I/O) disque.    

      SQL va donc, TOUJOURS, chercher à optimiser la sélection (Pour Order By, c'est facile de trier en mémoire).

     • En réutilisant des index, sauf quand le nombre d'enregistrement correspondant à la sélection est élévé (plus de qq %)

    • sinon, en utilisant des techniques comme la table de haschage, SI ALWCPYDTA(*OPTIMIZE)


    L'idéal étant de trouver un index portant sur la sélection ET le critère  de jointure ,  par exemple :

    SELECT * FROM CLIENTS JOIN CDES on CLIENTS.NOCLI = CDES.NOCLI
                WHERE DEPCLI = 44
    Ici, l'idéal serait index sur NOCLI ET DEPCLI

    L'index parfait est celui qui contient toutes les données, évitant d'aller chercher le reste dans la table.
  • Si vous avez le choix , mettez la clef la plus restrictive en premier
  • Mutualisez les index, un index avec DEPCLI puis NOCLI sera utilisé pour une recherche sur le département seul.
    (ne faites donc pas un index avec DEPCLI tout seul, il ne sert à rien !)
  • Ne confondez pas nombre de logiques et nombre d'index :
    • le système ne créé jamais 2 fois le même index (partage implicite de chemin d'accès)
      • si vous créez un logique L1 avec comme clé K1
        puis un logique L2 avec comme clé K1 -> L2 est une enveloppe vide pointant sur L1
        • si vous détruisez L1, l'index est déplacé dans L2
      • si vous créez un index (CREATE INDEX) puis un logique, ils partagent le C.A
      • si vous créez un logique puis un index, ça dépent
        • le logique ayant été crée avec PAGESIZE(64) : oui
        • le logique ayant été créé avec une taille plus petite (le défaut) : non
      • si vous définissez une PRIMARY KEY puis un logique, ils partagent le C.A
  • Enfin, si vous faites des LF avec sélection d'enregistrement, ajoutez DYNSLT et un index existant sera certainement réutilisé
    (partage implicite de chemin d'accès, montré par DSPFD)

  • Vérifiez tout cela avec Visual Explain !

    voyez enfin notre cours sur la réutilisation des logiques en version 7.2

 



Copyright © 2019 VOLUBIS