html

Migrer des LOB-segments d’Oracle vers PostGreSQL

Depuis des années, ora2pg permet la migration de données d’Oracle vers PostGreSQL. Une des ombres au tableau de cet outil est le traitement des LOBs (Large OBjects) et plus particulièrement de BLOBs (Binary Large OBjects), qui même optimisé reste particulièrement lent.

J’ai récemment testé l’aventure sur une table contenant 8 millions de lignes pour 27 Go de BLOB-segments. Avec ora2pg l’extraction a pris, en utilisant le parallélisme que perl me permet sur un serveur de 4 vCPU et 32 Go de mémoire, près de 5 jours.
(suite…)

La clause MODEL d’Oracle – Pour prévoir

code SQL

CHAPITRE 2: Modélisation prédictive

Dans le précédent article, on a pu voir que la clause MODEL d’Oracle permettait de faire des calculs un peu comme on les ferait avec un tableur en utilisant le résultat de certaines cellules pour en calculer d’autres.

La modélisation permet aussi de créer des lignes comlpètes de toute pièce en s’appuiant sur les précédentes. Ces types de modélisations sont généralement utilisés pour se projeter dans l’avenir et donc intéressant pour les modèles décisionnels

Je vais construire ici un modèle fictif, pour montrer la méthode, qui va donc se baser sur un historique et extrapoler un avenir.

Le modèle à utiliser sera celui d’un ingénieur commercial qui voudrait prédire l’évolution de ses tarifs. Rien que du très classique en fin de compte. Les règles de calcul vont être lesquelles ?

  • Les tarifs sont révisés annuellement
  • Les tarifs sont révisés à date de renouvellement de contrat
  • La révision des tarifs aura pour objectif d’être égale à l’évolution annuelle de l’indice syntec 2 mois avant la date anniversaire du contrat.
  • Il y a deux indices syntec, on se base sur celui qui correspond à la date d’origine du contrat. L’ancienne valeur a été diffusée jusqu’à la date du 1er juillet 2022 et qu’à partir de là il se calcul en multipliant le nouvel indice par une constante égale à 0,97975.

Je vais donc

  • Extrapoler l’indice syntec jusqu’en juin 2025
  • Extrapoler l’ancienne indice par rapport au nouveau à partir d’aout 2022
  • Calculer les variations annuelles entre juillet 2023 et juin 2025

je prendrai comme hypothèse, qu’au pire des cas, l’indice n’évoluera pas plus qu’il n’a évolué l’une de ces deux dernières années.

(suite…)

La clause MODEL d’Oracle – Plus besoin de tableur

code SQL

CHAPITRE I: Les bases de la clause MODEL

La clause MODEL d’Oracle est utilisée pour générer des valeurs sous condition. Elle peut générer des valeur à partir de rien ou à partir de cellules existantes dans la table ou déjà calculées avec cette même clause. Cela en fait un outil de calcul puissant qui bien utilisé rend obsolète votre tableur préféré.

Premier exemple de génération.

Je veux générer de toutes pièces un tableau (une table) qui va me servir à calculer phi (ou nombre d’or).

  • Je sais que la valeur théorique de phi est de (1+√5)/2.
  • Je sais aussi que la suite de Fibonacci permet d’approcher ce nombre en divisant un de ses termes par le précédent (phi ≅ fibo(n)/fibo(n-1))
  • Je suis curieux, je veux aussi calculer l’écart entre le rapport fibo(n)/fibo(n-1) et la valeur théorique

(suite…)

Installer Oracle XE 18c sur Centos 8

travail sur ordinateur

Cette procédure d’installation se déroule avec l’utilisateur root. Elle a été déroulée sur une VM centos 8 minimaliste telle que distribuée par linuxvimages.com.

Elle permet d’installer Oracle XE sur une VM Centos 8, l’intérêt est essentiellement pédagogique. En effet Oracle XE est très limitée (12 Go de données utilisateur au maximum, 2Gb de mémoire, 2 Threads … et 3 PDB, mais on s’en cogne ça ne sert à rien sur des volumétries si faibles).

Malgré ces limitations les interpréteurs SQL et PL/SQL sont complets ce qui en fait un excellent outil de formation.
(suite…)

Git et Visual Studio Code, pour un suivi efficace du code

code phpL’idée de maintenir un code de qualité pour à peu près tout est reste souvent un veux pieux. On verra ici comment utiliser Git et Visual Studio Code qui permettent de travailler proprement et rapidement. Cependant, leur mise en place bien qu’aisée n’est pas évidente. Ce petit guide est mon aide mémoire personnel pour les installer.

Télécharger et configurer GIT

Télécharger Git pour Windows ou votre OS préféré. En fin de configuration, lancer le shell bash, puis passer les commandes suivantes afin de paramétrer les informations relatives à votre dépot :

(suite…)

Métrologie

Nombre de redo log files générés, dataviz

Encore ce nombre de redo log files générés … pfff on voit ça tout le temps

Ce que l’on souhaite faire c’est afficher simplement le nombre de redo log files générés en mode graphiquesous forme de heat-map. Pour ce faire on utilise highcharts qui a le bon goût d’être gratuit pour un usage récréatif et non commercial. Et parce qu’on aime s’amuser on testera aussi avec plotly qui est gratuit tout court.

Pour ce faire, On choisit de séparer le code HTML, du javascript et des données de manière ce que chaque partie de code puisse être réutilisés au maximum.

(suite…)

Scripts SQL

Branchements et boucles en pur SQL

SQL est pratique mais il est compliqué de produire un script SQL qui s’adapte à toutes les versions de la base oracle ou qui réagit en fonction de certains résultats de requêtes. Cet article pour donner des astuces de scripting afin de gérer des branchements et boucles en pur SQL et de pouvoir créer des scripts adaptifs.
(suite…)

Arrondir une date

On est souvent confronté à la problématique suivante, comment arrondir une date en dehors des sentiers tracés par trunc (la minute, l’heure, la semaine …) et donc stackoverflow donne ces exemples de réponses pour arrondir une date à 10 minutes mais qui sont facilement extrapolables à d’autres intervals :

Le plus compréhensible

SELECT
  sysdate, TRUNC(sysdate, 'MI') - MOD(TO_CHAR(sysdate, 'MI'), 10) / (24 * 60)
FROM dual;

Le moins lisible

select
  trunc(sysdate, 'mi') - numtodsinterval(mod(EXTRACT(minute FROM cast(sysdate as timestamp)), 10), 'minute')
from dual;

Le plus à jour

select
  trunc(sysdate, 'mi') 
  - mod(EXTRACT(minute FROM cast(sysdate as timestamp)), 10) / (24 * 60)
from dual;

Au niveau du coût pour les 3 on a (avec un temps d’execution identique inférieur au centième de seconde) :

-----------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------
|   0 | SELECT STATEMENT |      |     1 |     2   (0)| 00:00:01 |
|   1 |  FAST DUAL       |      |     1 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          0  consistent gets
          0  physical reads
          0  redo size
        657  bytes sent via SQL*Net to client
        520  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

Un exemple ?

alter session set NLS_DATE_FORMAT='YY-MM-DDHH24:MI:SS' ;

col DT   for a8 wrap
col S10  for a8 wrap
col M    for a8 wrap
col M5   for a8 wrap
col M10  for a8 wrap
col M15  for a8 wrap
col M30  for a8 wrap
col H2   for a8 wrap
col H3   for a8 wrap
col H6   for a8 wrap
col H8   for a8 wrap
col H12  for a8 wrap
col DAY  for a8 wrap
col WEEK for a8 wrap

select sysdate                                                                                     DT
     , sysdate - mod(EXTRACT(second FROM cast(sysdate as timestamp)), 10) / (24 * 60 * 60)         S10
     , trunc(sysdate, 'mi')                                                                        M
     , trunc(sysdate, 'mi') - mod(EXTRACT(minute FROM cast(sysdate as timestamp)), 5) / (24 * 60)  M5
     , trunc(sysdate, 'mi') - mod(EXTRACT(minute FROM cast(sysdate as timestamp)), 10) / (24 * 60) M10
     , trunc(sysdate, 'mi') - mod(EXTRACT(minute FROM cast(sysdate as timestamp)), 15) / (24 * 60) M15
     , trunc(sysdate, 'mi') - mod(EXTRACT(minute FROM cast(sysdate as timestamp)), 30) / (24 * 60) M30
     , trunc(sysdate, 'hh24') - mod(EXTRACT(hour FROM cast(sysdate as timestamp)), 2) / 24         H2
     , trunc(sysdate, 'hh24') - mod(EXTRACT(hour FROM cast(sysdate as timestamp)), 3) / 24         H3
     , trunc(sysdate, 'hh24') - mod(EXTRACT(hour FROM cast(sysdate as timestamp)), 6) / 24         H6
     , trunc(sysdate, 'hh24') - mod(EXTRACT(hour FROM cast(sysdate as timestamp)), 8) / 24         H8
     , trunc(sysdate, 'hh24') - mod(EXTRACT(hour FROM cast(sysdate as timestamp)), 12) / 24        H12
     , trunc(sysdate, 'dd')                                                                        DAY
     , trunc(sysdate, 'd')                                                                         WEEK
from dual
/
DT S10 M M5 M10 M15 M30 H2 H3 H6 H8 H12 DAY WEEK
18-05-14
17:28:39
18-05-14
17:28:30
18-05-14
17:28:00
18-05-14
17:25:00
18-05-14
17:20:00
18-05-14
17:15:00
18-05-14
17:00:00
18-05-14
16:00:00
18-05-14
15:00:00
18-05-14
12:00:00
18-05-14
16:00:00
18-05-14
12:00:00
18-05-14
00:00:00
18-05-13
00:00:00

C’était pourtant pas si compliqué

Retrouver les informations relatives à ma session

Je veux savoir quelle est ma session au niveau de v$session et à quel processus OS elle correspond

La requête à passer est la suivante :

set pages 0 lines 230 newp none emb on

col machine for a25

select v.SID, v.USERNAME, v.MACHINE, v.PROGRAM, v.TERMINAL, SPID "OS PID", v.process
from v$session v inner join v$process p on v.paddr=p.addr
where v.AUDSID=USERENV('SESSIONID')
and v.MACHINE=SYS_CONTEXT('USERENV','HOST')
and v.TERMINAL=USERENV('TERMINAL')
/

Son résultat :

       
SID        USERNAME                       MACHINE                   
---------- ------------------------------ ------------------------- 
       633 SYS                            srvorcl.ojo.fr            
       
PROGRAM                                          TERMINAL                       
------------------------------------------------ ------------------------------      
sqlplus@srvorcl.ojo (TNS V1-V3)                  pts/2                          

OS PID                   PROCESS
------------------------ ------------------------  
147476                   147469       

On a OS PID qui correspond à l’identifiant du process de connexion de SQLPLUS à la base de données et process qui correspond l’indentifiant du process sqlplus

ps -edf | grep 147476 | grep -v grep
oracle   147476 147469  0 15:12 ?        00:00:00 oracleTECH (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))

ps -edf | grep 147469 | grep -v grep
oracle   147469 197784  0 15:12 pts/2    00:00:00 sqlplus
oracle   147476 147469  0 15:12 ?        00:00:00 oracleORCL (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))

Pour tuer la connexion sans tuer sqlplus (et se retrouver en mode nolog) c’est le process 147476 qu’il faut tuer.

C’était pourtant pas si compliqué

Identifier sa session

En PL/SQL

exec sys.dbms_session.set_identifier          ('identifiant de session')
exec sys.dbms_application_info.set_client_info('info client')
exec sys.dbms_application_info.set_module     ('module', 'action')

Eventuellement, si l’on veut ne changer que l’action

exec sys.dbms_application_info.set_action('action')

En PHP

<?php 
 oci_set_client_identifier($db , 'identifiant de session'); 
 oci_set_client_info      ($db , 'info client'); 
 oci_set_module_name      ($db , 'module'); 
 oci_set_action           ($db , 'action'); 
?>

Retrouver ces informations

select sys_context('USERENV', 'CLIENT_IDENTIFIER') as "client identifier"
     , sys_context('USERENV', 'CLIENT_INFO') as "client info"
     , sys_context('USERENV', 'MODULE') as module
     , sys_context('USERENV', 'ACTION') as action
from sys.dual ;

Avec un peu de mise en forme

SQL> col "client identifier" for a25
SQL> col "client info" for a17
SQL> col module for a17
SQL> col action for a17

SQL> /

client identifier         client info       MODULE            ACTION
------------------------- ----------------- ----------------- -----------------
identifiant de session    info client       module            action

C’était pourtant pas si compliqué

PS: On peut aussi le faire en java ou en .Net si tant est qu’on utilise encore des trucs aussi dépassés ou encore en C via la bibliothèque OCI1 si l’on est résolument moderne. Tout cela est détaillé dans l’excellent Troubleshooting Oracle Performance de Christian Antognini paru chez APress au chapitre 2 pages 45 à 48. Et de manière plus cryptique et éparpillée dans la documentation de l’éditeur.


1. OCI pour Oracle Call Interface, livré par Oracle avec tous les “clients”