Je n’ai pas voulu mettre optimisation dans le titre de l’article, c’est pourtant bien ce qui nous est souvent demandé.
Avant de chercher à optimiser les requêtes, il est utile de vérifier que quelques bonnes pratiques de base sont respectées dans l’écriture de la requête !

Dans le cas traité, on s’intéresse particulièrement à plusieurs éléments :

  • critères de jointure
  • critères de sélection
  • critères de groupage
    Objectif recherché : que tous ces critères soient exprimés, si possible, sans calcul !
    Une zone calculée ne peut être prise en charge via un index par l’optimiseur … nous allons donc réécrire tout ce qui a été écrit d’une façon « humaine » !

Exemple

La requête utilisée dans cet article est un extrait d’un requête réelle, pour laquelle les noms de tables et colonnes ont été modifiées …

Critère de jointure

Ce point n’impacte que peu les performances, car le moteur SQL réécrit la requête pour nous, mais apporte plus de lisibilité.
On évite ce genre de syntaxe (produit cartésien) :

SELECT …
FROM ADHENT,
     ADHDET
WHERE (ADHENT.GJCMP = ADHDET.GACMP#
              AND ADHENT.GJGL# = ADHDET.GAGL#A
              AND ADHDET.GAACCD = '1')
          AND ((ADHDET.GATYPE IN (
                      'EX',
                      'IN'
                  ))

Pour exprimer sur la jointure les critères :

select ADHENT.*
from ADHENT
join ADHDET ON (ADHENT.GJCMP = ADHDET.GACMP#
AND ADHENT.GJGL# = ADHDET.GAGL#A
AND ADHDET.GAACCD = '1')
WHERE (ADHDET.GATYPE IN (
'EX',
'IN'
)) ;

Critères de sélection

Requête de départ :

select ADHENT.*
from ADHENT
join ADHDET ON (ADHENT.GJCMP = ADHDET.GACMP#
AND ADHENT.GJGL# = ADHDET.GAGL#A
AND ADHDET.GAACCD = '1')
WHERE ADHDET.GATYPE IN ( 'EX', 'IN' )
AND (ADHENT.GJACMO <> 13)
AND ADHENT.GJCMP IN ('10')
AND CASE
WHEN ADHENT.GJJLDT = 0 THEN '01/01/9999'
ELSE DATE( SUBSTR(ADHENT.GJJLDT, 5, 2) || '/' ||
SUBSTR(ADHENT.GJJLDT, 7, 2) || '/' ||
SUBSTR(ADHENT.GJJLDT, 1, 4))
END BETWEEN '2016-01-01' AND '2017-12-31'
AND SUBSTR(ADHENT.GJGL#, 1, 6) BETWEEN '615540' AND '615540'
AND CASE
WHEN TRIM(ADHENT.GJLTG#) = '' THEN 'N'
ELSE 'Y'
END = 'N'

Il est possible de remplacer toutes les valeurs calculées et de les inverser !

   AND CASE
         WHEN ADHENT.GJJLDT = 0 THEN '01/01/9999'
         ELSE DATE( SUBSTR(ADHENT.GJJLDT, 5, 2) || '/' ||
                    SUBSTR(ADHENT.GJJLDT, 7, 2) || '/' ||
                    SUBSTR(ADHENT.GJJLDT, 1, 4))
       END BETWEEN '2016-01-01' AND '2017-12-31'

Devient  :

AND ADHENT.GJJLDT between int(date('2016-01-01')) AND int(date('2017-12-31'))

Sélection sur code :

   AND SUBSTR(ADHENT.GJGL#, 1, 6) BETWEEN '615540' AND '615540'

Devient :

AND ADHENT.GJGL# BETWEEN '615540' ||'0000000000' AND '615540' || '9999999999'

Sélection sur code :

   AND CASE
         WHEN TRIM(ADHENT.GJLTG#) = '' THEN 'N'
         ELSE 'Y'
       END = 'N'

Devient :

AND ADHENT.GJLTG# = ''

Ce dernier exemple illustre bien la capacité du cerveau humain à raisonner et non pas à exprimer des critères techniques !

Critères de groupage (et mise en forme)

Le groupage est souvent effectué en dernier, c’est-à-dire après l’ensemble des jointures. Vous êtes alors contraints d’ajouter un nombre important de colonnes dans le groupage, colonnes faisant l’objet de mise en forme pour un affichage adapté à l’utilisateur, et donc sur des zones calculées !
Nous proposons l’inverse :

  • d’abord on calcule les données, nécessitant groupage
  • ensuite on va chercher, par des jointures, des éléments complémentaires et on met en forme (calcul) les valeurs
    Pour cela les CTE (Common Table Expressions) nous sont d’un grand secours.

Par exemple :

with tmp as (
   SELECT ADHENT.GJCMP,
          ADHENT.GJGL#,
          ADHENT.GJJLTP,
          ADHENT.GJJLCD, 
          ADHENT.GJJLNO,
          ADHENT.GJINV#, 
          ADHENT.GJDESC,
          ADHENT.GJJLDT,
          ADHENT.GJMVM#,
          ADHENT.GJTYPE,
          ADHENT.GJLTG#,
          ADHENT.GJLTGD,
          SUM(ADHENT.GJAMT$) as somme1,
          SUM( CASE
                 WHEN ADHENT.GJAMT$ > 0.00 THEN ADHENT.GJAMT$
               END) as somme2,
          SUM(
               CASE
                 WHEN ADHENT.GJAMT$ < 0.00 THEN (-1 * ADHENT.GJAMT$)
               END) as somme3
   from ADHENT
   join ADHDET ON ...
   WHERE ...
   GROUP BY ADHENT.GJCMP,
            ADHENT.GJGL#,
            ADHENT.GJJLTP,
            ADHENT.GJJLCD,
            ADHENT.GJJLNO,
            ADHENT.GJINV#,
            ADHENT.GJDESC,
            ADHENT.GJJLDT,
            ADHENT.GJMVM#,
            ADHENT.GJTYPE,
            ADHENT.GJLTG#,
            ADHENT.GJLTGD )

select tmp.GJCMP,
        SUBSTR(tmp.GJGL#, 7, 4),
        SUBSTR(tmp.GJGL#, 1, 6),
        tmp.GJJLTP,
        tmp.GJJLCD || '-' || RIGHT(CONCAT('00000000', TRIM(CHAR(tmp.GJJLNO))), 8),
        tmp.GJJLNO,
        TRIM(tmp.GJINV#),
        tmp.GJDESC,
        CASE WHEN tmp.GJJLDT = 0 THEN '01/01/9999'
             ELSE DATE( SUBSTR(tmp.GJJLDT, 5, 2) || '/' ||
                        SUBSTR(tmp.GJJLDT, 7, 2) || '/' ||
                        SUBSTR(tmp.GJJLDT, 1, 4))
        END,
        tmp.GJMVM#,
        TRIM(tmp.GJTYPE),
        tmp.GJLTG#,
        tmp.GJGL#,
        ADHCMP1.ZLARGN,                 
        TRIM(ADHCMP2.ZRNAME),           
        CASE WHEN tmp.GJLTGD = 0 THEN '01/01/9999'
             ELSE DATE( SUBSTR(tmp.GJLTGD, 5, 2) || '/' ||
                        SUBSTR(tmp.GJLTGD, 7, 2) || '/' ||
                        SUBSTR(tmp.GJLTGD, 1, 4))
        END,
        somme1,
        somme2,
        somme3
 from tmp 
   LEFT OUTER JOIN ADHCMP1 ON ADHCMP1.ZLCMP  = tmp.GJCMP
                           AND ADHCMP1.ZLLOC  = SUBSTR(tmp.GJGL#, 7, 4)
   LEFT OUTER JOIN ADHCMP2 ON ADHCMP1.ZLCMP  = ADHCMP2.ZRCMP
                           AND ADHCMP1.ZLIRGN = ADHCMP2.ZRRGN ;

Avec ces quelques règles, simples dans leur principe, vous vous assurez que le moteur SQL pourra utiliser pleinement vos index. Cela ne signifie pas qu’il ne sera pas nécessaire d’optimiser par la suite.

Pour finir le cas concret évoqué ici :
– 4 fichiers dans la jointures :
– 500 Millions , 1 Million, 1.000 et 70 enreg
– 4.600 enreg en retour

Requête d’origine : 2 min 40 s (ce qui est déjà très bien, avec un scan de table sur le plus gros fichier).
Après réécriture : 40 ms

Bien sûr, les index nécessaires étaient déjà en place pour atteindre ce niveau de temps de réponse.

Encore une fois, SQL est le meilleur moyen d’accéder à la donnée, aussi complexe soit elle.

Par le meilleur, j’entends :

  • le plus simple : écrire un programme RPG/COBOL équivalent demanderait une quantité de code importante (et donc probabilité de bug)
  • le plus efficace (40 ms) : à condition que l’on donne à SQL les moyens d’être efficace

En conclusion : travailler d’abord sur la donnée, occupez vous ensuite de la mise en forme !

, Comparer les PTF de 2 systèmes

Vous avez besoin de connaitre les niveaux de PTF de 2 systèmes.

Voici comment vous pouvez faire pour comparer les PTF de 2 systèmes, avant on pouvait le faire par Navigator for i – voir le post https://www.gaia.fr/comparer-le-niveau-de-ptf-entre-2-systemes-ibmi/

Pour les groupes

Vous avez la vue QSYS2.GROUP_PTF_INFO

Vous allez devoir comparer les niveaux installés sur les 2 systèmes. Voici comment le faire simplement :

Vous devrez faire une extraction des éléments sur le système à comparer par exemple

create table gaia.remote_ptf as (
select * from QSYS2.GROUP_PTF_INFO
) with data

Vous envoyez le fichier sur la machine cible

select a.PTF_GROUP_NAME, a.PTF_GROUP_LEVEL, b.PTF_GROUP_LEVEL
from QSYS2.GROUP_PTF_INFO a join gaia.remote_ptf b on
A.PTF_GROUP_NAME = B.PTF_GROUP_NAME

pour n’avoir que les différences

select distinct
substr(a.PTF_GROUP_NAME, 1, 30) ,
a.PTF_GROUP_LEVEL, b.PTF_GROUP_LEVEL
from QSYS2.GROUP_PTF_INFO a join gaia.remote_ptf b on
A.PTF_GROUP_NAME = B.PTF_GROUP_NAME
where a.PTF_GROUP_LEVEL <> b.PTF_GROUP_LEVEL

Attention vous avez 2 niveaux de groupe dans le fichier, il faudrait améliorer le script en prenant un max pour avoir le plus haut sur les 2 systèmes

Exemple :

with
LCL (PTF_GROUP_NAME, PTF_GROUP_LEVEL) as
(
SELECT substr(PTF_GROUP_NAME, 1, 20), max(PTF_GROUP_LEVEL) FROM
QSYS2.GROUP_PTF_INFO GROUP BY PTF_GROUP_NAME
),
RMT (PTF_GROUP_NAME, PTF_GROUP_LEVEL) as
(
SELECT substr(PTF_GROUP_NAME, 1, 20), max(PTF_GROUP_LEVEL) FROM
gaia.remote_ptf GROUP BY PTF_GROUP_NAME
)
select A.PTF_GROUP_NAME, A.PTF_GROUP_LEVEL, B.PTF_GROUP_LEVEL
from LCL A join RMT B on A.PTF_GROUP_NAME = B.PTF_GROUP_NAME

Pour les PTF unitaires

Vous avez la vue QSYS2.PTF_INFO, vous pouvez également utiliser un DSPPTF en OUTFILE

Vous allez devoir trouver les PTF manquantes

Vous devrez faire une extraction des éléments sur le système à comparer par exemple

create table gaia.remote_ptf1 as (
select * from QSYS2.PTF_INFO
) with data

Vous envoyez le fichier sur la machine cible

Pour avoir les PTF qui manquent sur le remote :

SELECT a.PTF_PRODUCT_ID, a.PTF_IDENTIFIER
FROM QSYS2.PTF_INFO a exception join
gaia.remote_ptf1 b on
a.PTF_PRODUCT_ID = b.PTF_PRODUCT_ID and
a.PTF_IDENTIFIER = b.PTF_IDENTIFIER

Si voulez les PTF qui manquent sur la source, le plus simple est de changer l’ordre des fichiers :

SELECT a.PTF_PRODUCT_ID, a.PTF_IDENTIFIER
FROM gaia.remote_ptf1 a exception join
QSYS2.PTF_INFO b on
a.PTF_PRODUCT_ID = b.PTF_PRODUCT_ID and
a.PTF_IDENTIFIER = b.PTF_IDENTIFIER

Remarque :

Vous pouvez utiliser une connexion DRDA pour comparer vos fichiers sans les envoyer, si c’est paramétré chez vous
exemple :
select distinct
substr(a.PTF_GROUP_NAME, 1, 30) ,
a.PTF_GROUP_LEVEL, b.PTF_GROUP_LEVEL
from QSYS2.GROUP_PTF_INFO a join .QSYS2.GROUP_PTF_INFO b on
A.PTF_GROUP_NAME = B.PTF_GROUP_NAME
where a.PTF_GROUP_LEVEL <> b.PTF_GROUP_LEVEL

Vous avez des outils comme ARE qui permettent de faire ce type d’opération


un lien avec un exemple DSPPTF OUTFILE
https://www.ibm.com/support/pages/ptfs-comparing-ptfs-between-systems

, Faire un CSV avec SQL

Il existe plusieurs solutions pour faire du CSV, la plus connue c’est en utilisant la commande CPYTOIMPF, mais vous pouvez générer directement un fichier CSV en utilisant SQL, voici un petit tutoriel pour vous aider :

Vous devrez utiliser les procédures QSYS2.IFS_WRITE*

https://www.ibm.com/docs/en/i/7.4?topic=is-ifs-write-ifs-write-binary-ifs-write-utf8-procedures

Voici un exemple qui comporte la génération du fichier, l’ajout d’un entête et la génération des listes de détail. Nous avons choisi de faire sans délimiteur et avec « ; » comme séparateur. Le fichier obtenu est directement lisible par Excel.

Si vous voulez un délimiteur voici une variante sur les select avec  » comme délimiteur

Pour les entêtes de ligne :

LINE => ‘ »Les_options » ; « Les_commandes »‘)

Pour les lignes de détail, on enlève les blancs :

select ‘ »‘ concat trim(option) concat ‘ » ; « ‘ concat trim(command) concat ‘ »‘ as option_txt from qgpl.qauoopt

BEGIN
  -- Créér ou remplacer le fichier dans l'IFS
  CALL QSYS2.IFS_WRITE_UTF8(PATH_NAME =>'les_options_pdm.csv', 
                       LINE => '', 
                       OVERWRITE => 'REPLACE', 
                       END_OF_LINE => 'NONE');
  -- Mettre l'entête de colonne                     
  CALL QSYS2.IFS_WRITE_UTF8(PATH_NAME =>'les_options_pdm.csv', 
                       LINE => 'Les_options ; Les_commandes'); 
  -- Ecriture d'une ligne obtenue dans le select  
  FOR select option concat ';' concat command  as option_txt from qgpl.qauoopt DO
    CALL QSYS2.IFS_WRITE_UTF8(PATH_NAME => 'les_options_pdm.csv', 
                         LINE => option_txt);
  END FOR;
END;

Dans cet exemple, on a utilisé la procédure QSYS2.IFS_WRITE_UTF8 pour générer le fichier directement en UNICODE et éviter les problèmes de CCSID, c’est le sens de l’histoire …

Nous n’avons pas précisé de répertoire. Le fichier est créé dans le répertoire par défaut de l’utilisateur, en principe /home/<user>

.

Conclusion :

C’est une solution simple et efficace qui permet de générer un fichier sans passer par un fichier intermédiaire en DB2.

Si vos zones sont numériques vous devrez les convertir par la fonction CHAR()

Merci Nath pour ton aide.

, , Informations sur les SAVF

Les groupes DB2 pour la TR2 de la V7R5 et de la TR8 de la V7R4 sont disponibles, une des nouveautés c’est les vues sur les fichiers de sauvegarde

La première vue sur les SAVF SAVE_FILE_INFO permet d’avoir des informations sur le SAVF

par exemple
vous voulez connaitre les SAVF qui date de plus de 6 mois

select * from QSYS2.SAVE_FILE_INFO
where SAVE_TIMESTAMP < current date – 6 month
order by SAVE_TIMESTAMP desc

Vous pouvez par exemple utiliser la fonction SQL QCMDEXC pour faire le ménage plus d’informations ici
https://www.gaia.fr/qcmdexc-en-fonction-sql/

La deuxième vue sur les objets sauvegardés dans les SAVF, QSYS2.SAVE_FILE_OBJECT permet d’avoir des informations sur les ojets contenus dans le SAVF

Par exemple vous voulez savoir, si un objet est dans une sauvegarde et sa date de sauvegarde

select * from QSYS2.SAVE_FILE_OBJECTS
where OBJECT_NAME = ‘votre objet’ and OBJECT_TYPE = ‘votre type’
order by SAVE_TIMESTAMP desc

Attention
Ces fonctions sont à lancer en batch, c’est des informations qui mettent du temps à être extraites

, Migration en V7R4 et IFS

Il est possible que vous ayez un effet de bord sur les fichiers téléchargés par FTP ou SFTP par exemple dans vos cpyfrmstmf ou cpyfrmimpf vous avez un plantage.

Les fichiers étaient jusqu’ici encodés en CCSID = 819 et maintenant par défaut, ils sont encodés en CCSID = 1208

Le problème est référencé ici

https://www.ibm.com/support/pages/after-v7r4-upgrade-encoding-scheme-not-compatible-utilizing-gifsgatecpyfrmstmf-gentran-server-iseries

En résumé, vous devez rajouter une variable d’environnement et redémarrer vos services

Voici comment ?

// Ajout d’une variable d’environnement

ADDENVVAR ENVVAR(PASE_DEFAULT_UTF8) VALUE(N) LEVEL(*SYS)

// Redémarrage du FTP

STRTCPSVR SERVER(*FTP)

ENDTCPSVR SERVER(*FTP)

// Redémarrage du SFTP

ENDTCPSVR SERVER(*SSHD)

STRTCPSVR SERVER(*SSHD)

Conclusion :

Ca vous permet de contourner le problème, mais le mieux est de passer en unicode donc CCSID = 1208

Les fonctions géospatiales

Premier test sur les fonctions géospatiales, elles sont désormais intégrées à DB2

Vous pouvez indiquer les coordonnées GPS d’un lieu dans une zone, et vous pourrez ensuite faire des calculs,
de distance , de superficie, etc …

C’est des zones de type QSYS2.ST_POINT, par exemple pour indiquer des coordonnées GPS, mais vous pouvez également indiquer des formes comme des lignes ou des polygones ..

Voici un premier exemple

— Création table des salariés avec leur lieu de travail

create table GDATA.SALARIE
(ID int,
NOM varchar(30),
PRENOM varchar(30),
MAISON QSYS2.ST_POINT,
TRAVAIL QSYS2.ST_POINT);

— Insertion dans la table des informations
Vous pouvez les trouver ici les coordonnées GPS:
https://www.coordonnees-gps.fr/

le gouvernement mais également à disposition un site

https://adresse.data.gouv.fr/api-doc/adresse

Vous pouvez interroger par CURL ou API bien sur par API en SQL

Exemple pour Gaia:

sous qsh

curl « https://api-adresse.data.gouv.fr/search/?q=41+rue+diebold&postcode=69009 »

résultat

Dans un browser

https://api-adresse.data.gouv.fr/search/?q=41+rue+Diebold&postcode=69009

INSERT INTO GDATA.SALARIE VALUES(1, ‘Géronimo’, ‘Cohen’,
QSYS2.ST_POINT(‘point (45.7542616 4.9152559)’),
QSYS2.ST_POINT(‘point (45.7726 4.8033)’)
) ;

Par Api

VALUES QSYS2.HTTP_GET(
‘https://api-adresse.data.gouv.fr/search/?q=41+rue+Diebold&postcode=69009’);

— Calculé la distance entre 2 points en mètres
— Représentation en coordonnées des zones

SELECT
ST_ASTEXT(maison) as coord_maison,
ST_ASTEXT(travail) as coord_travail,
st_distance(maison , travail) as distance from GDATA.SALARIE ;

Résultat :

.

Vous pouvez par exemple, facilement calculer les salariés qui habitent à plus de 100 km de leur lieu de travail.

SELECT « ID », NOM, PRENOM
from GDATA.SALARIE
where st_distance(maison , travail) > 100000 ;

On complète

— Création table des docteurs
create table GDATA.DOCTEUR
(ID int,
NOMDOC varchar(30),
VILLE varchar(30),
CABINET QSYS2.ST_POINT);

— insertion d’une liste de docteurs

INSERT INTO GDATA.DOCTEUR VALUES(1, ‘Docteur1’, ‘Lyon’,
QSYS2.ST_POINT(‘point (45.7679223 4.8445736)’)
) ;

INSERT INTO GDATA.DOCTEUR VALUES(2, ‘Docteur2’, ‘Marseille’,
QSYS2.ST_POINT(‘point (43.2978337 5.3693324)’)
) ;

INSERT INTO GDATA.DOCTEUR VALUES(3, ‘Docteur3’, ‘Paris’,
QSYS2.ST_POINT(‘point (48.8532238 2.3678865)’)

) ;

— Je veux les docteurs à moins de 10 km du domicile du salarié

Select b.nomdoc, b.ville, st_distance(a.maison , b.cabinet) as distance
from gdata.salarie a , gdata.docteur b
where st_distance(a.maison , b.cabinet) < 10000 ;

Le résultat

Conclusions :

Il y a des fonctions beaucoup plus poussées, et on imagine bien le type d’application qu’on pourra faire, donc on peut prévoir dès à présent une zone de géolocalisation dans des fichiers clients qu’on va créer, voir modifier .

Plus d’informations ici

https://www.ibm.com/docs/en/i/7.5?topic=analytics-geospatial-functions

, Comparer 2 monitors de base de données

Vous avez collecté 2 monitors de base de données, du genre avant après une mise en prod et vous voulez les comparer

La première solution est d’utiliser ACS
SQL Performance Center
Moniteur de performances

Mais vous pouvez faire des opérations assez similaire en utilisant SQL

https://www.ibm.com/docs/en/i/7.4?topic=formats-sql-table

Voici 2 exemples de requêtes

En nombre en ID record

WITH dbmon1 (QQRID, total1) AS (
         SELECT QQRID,
                COUNT(*)
             FROM votrebib.QZGxxxxxx     << monitor 1
             GROUP BY QQRID
     ),
     dbmon2 (QQRID, total2) AS (
         SELECT QQRID,
                COUNT(*)
             FROM votrebib.QZGyyyyyyy     << monitor 2
             GROUP BY QQRID
     )
    SELECT dbmon1.QQRID,
           dbmon1.total1,
           dbmon2.total2
        FROM dbmon1
             JOIN dbmon2
                 ON dbmon1.QQRID = dbmon2.QQRID

En temps d’exécution

WITH dbmon1 (QQRID, total1) AS (
         SELECT QQRID,
                sum(QQETIM - QQsTIM )
             FROM votrebib.QZGxxxxxxx    << monitor 1
             GROUP BY QQRID
     ),
     dbmon2 (QQRID, total2) AS (
         SELECT QQRID,
                 sum(QQETIM - QQsTIM )
             FROM votrebib.QZGyyyyyyyy   << monitor 2 
             GROUP BY QQRID
     )
    SELECT dbmon1.QQRID,
           dbmon1.total1,
           dbmon2.total2
        FROM dbmon1
             JOIN dbmon2
                 ON dbmon1.QQRID = dbmon2.QQRID

Après il vous faudra enquêter sur les différences que vous avez constaté

Exemple :


Avec l’ID , 3002 vous aurez les indexs à créer

, Les instructions SQL d’un profil

Vous voulez récupérer les requêtes SQL exécutées sous une session interactive

Si vous pouvez vous connecter sous le profil c’est relativement simple

Connectez vous sous le profil et sous STRSQL faites <F13>

Vous pouvez indiquer un fichier avec différentes options, le fichier par défaut s’appelle QSQLSESS de QGPL

La difficulté existe, si vous ne pouvez pas vous connecter sous le profil en effet ces informations sont stockées dans le profil.

Pour les voir vous devrez donc utiliser la commande DMPSYSOBJ

Comme ceci

DMPSYSOBJ OBJ(‘ISQLSTvotreuser*’) +
CONTEXT(QRECOVERY) TYPE(19) SUBTYPE(EE)

Vous obtenez un spool QPSRVDMP que vous pourrez analyser

Bien sur vous devez avoir le droit de dumper et le droit sur le profil

Pour vous aider nous avons fait un outil DMPSQLUSR que vous pouvez trouvez ici https://github.com/Plberthoin/PLB/tree/master/GTOOLS

Il n’est pas parfait, mais il produit un fichier SQLLISTE dans QTEMP qui contiendra toutes instructions exécutées

Rappel :

Vous pouvez également retrouver des informations sur l’exécution des requêtes dans des moniteurs DB ou dans le cache SQL.

, TR2 pour la V7R5

Les annonces de la TR2 pour la V7R5 sont sorties

Voici quelques infos sur les nouveauté de la TR

des nouvelles vues SQL
par exemple pour manipuler les fichiers SAVF
QSYS2.SAVE_FILE_INFO
QSYS2.SAVE_FILE_OBJECTS

sur les audits

Nouvelles fonctions table AUDIT_JOURNAL_XX pour analyser les types suivants
AP, AX, OR, PA, PF, PU, RA, RO, and RZ

ZLIB supporté par SQE

Sur DB2 , nouvelles fonctions SQL pour manipuler les dates et les heures

ADD_DAYS scalar function
ADD_HOURS scalar function
ADD_MINUTES scalar function
ADD_SECONDS scalar function
ADD_YEARS scalar function

Mais la principale nouveauté c’est l’arrivée de

Geospatial Analytics dans DB2 , c’est celle de Watson

https://www.ibm.com/docs/en/i/7.5?topic=analytics-best-practices-considerations

Vous voulez une définition regardez ici

https://fr.wikipedia.org/wiki/Analyse_spatiale

Ca préfigure de grosses nouveautés en matière d’analyse de données

RDV pour les premiers tests

plus d’informations ici

https://www.ibm.com/support/pages/ibm-i-75-tr2-enhancements

, , Database Information Finder

Si vous n’administré pas au quotidien votre base de données, mais que vous devez intervenir ponctuellement,
Vous avez un lien qui référence les principales opérations à faire et qui peut vous aider

https://www.ibm.com/docs/en/i/7.5?topic=database-information-finder

Vous avez 5 manières de chercher

DB2 tasks
SQL quick reference
DB2 and SQL examples
SQL statements
DB2 topics

Sélectionner l’information dans la liste et faite GO

Nous on utilise souvent la première

DB2 tasks

Vous voulez ajouter une zone, Appuyer vers Go, ca vous emmènera vers des liens qui référencera les opérations à effectuées.

Rappel :

Pour les exemples, vous avez aussi ACS qui en propose une liste

dans exécution de scripts SQL