Un conseil sur les colonnes de type date sous Oracle …

Les colonnes date sous Oracle permettent de stocker des dates « simples », sans heure, et aussi des dates avec l’heure. C’est sympa, mais cela provoque vite des erreurs dans les traitements d’alimentation ou dans les univers BO quand on effectue une jointure sur des colonnes de ce type contenant effectivement des heures.

Par exemple nous avons une table VENTES et la table calendrier TEMPS.
La table TEMPS est au jour, la PK est JOUR de type date – sans heure
La table VENTES a plusieurs dates, dont la date de vente ( colonne DATE_VENTE ) qui est aussi de type date, mais avec l’heure.
On a tendance à lier directement les tables sur les 2 colonnes, mais cela ne ramène aucune donnée car d’un côté on a l’heure, de l’autre on ne l’a pas …

Pire, une requête sur la table calendrier avec la date d’aujourd’hui ( sysdate ) semble légitime pour un utilisateur, mais la requête suivante ne renvoie rien !

SELECT * FROM TEMPS WHERE JOUR=SYSDATE

Il faut « enlever » l’heure avec la fonction trunc() pour avoir un résultat :
SELECT * FROM TEMPS WHERE JOUR=trunc(SYSDATE)

Généralement quand je n’ai pas la main sur le modèle je mets des trunc() un peu partout pour blinder les choses, mais c’est mieux quand en amont la conception et les normes sont bien faites et bien pensées, et que les noms des colonnes permettent de distinguer les dates avec heure et les dates sans.

Par exemple on peut nommer les colonnes avec heure en préfixant par
DATE_HEURE_ et les dates sans heure par DATE_ uniquement …
( ou DATE_ et DATH_ ou … cela dépend des normes of course … )
Idem pour l’univers BO, il est utile de préciser dans le nom des colonnes si on a affaire à une date avec heure ou sans.

Ainsi on sait tout de suite s’il faut rajouter un trunc() dans les jointures, et cela évite bien des erreurs …

Il reste le problème des dates qui contiennent des dates avec heure ET des dates sans heure, mais c’est une autre histoire …

Retour d’expérience sur … Sunopsis / ODI

Sunopsis est un ETL fondé par un français, Alain Dumas en 1998. Contrairement aux ETL qui possèdent leurs propres moteurs de transformation, Sunopsis est un génarateur de code qui repose sur une architecture d’intégration distribuée. Au lieu de transformer les données sur un serveur spécifique, il lance les traitements directements sur les bases de données, en exploitant au mieux les spécificités de chacune. Cette architecture est aussi définie comme ELT ( Extract/Load & Transform ).
Sunopsis a été racheté en 2006 par Oracle et depuis a été renommé en ODI ( Oracle Data Integrator ).

Les + :

  • les performances ( mode ELT )
  • les KM ( modules de connaissance ) qui définissent les process « standard » ETL comme la détection des doublons, des valeurs inconnues de tables de référence ( écartés dans une table d’erreur ),
    l’alimentation des tables ( en Insert pur, Insert en delta, en SCD … )
  • pas besoin de connaitre un nouveau langage, le SQL du SGBD suffit généralement !
  • debugage facile
  • reprise d’un plantage à partir d’un certain point ( où ça s’est planté, ou depuis le début, ou 3 sql avant … )
  • optimisation orientée SGBD donc facile ( un expert ETL n’est pas nécessaire, un DBA suffit )
  • l’analyse d’impact très fine
  • l’éditeur de requête sql qui permet de construire des requêtes assez complexes
  • les contextes qui facilitent le déploiement d’un environnement à un autre
  • la séparation modèle physique / modèle logique

Les – :

  • traitements unitaires basiques ( plusieurs tables constituent une requête qui alimente une seule table ) : il faut généralement utiliser des tables temporaires, le flux de la donnée n’est pas visible en un seul job.
  • nécessité de connaitre les SGBD … et des fonctions complexes dans certains cas
    comme pour les comparaisons relatives entre lignes,
    par ex pour comparer un statut par rapport au statut précédent
    –> fonctions analytiques oracle
  • la perte des dépendances pour l’analyse d’impact sur certains traitements
  • la prise en main – il faut bien décomposer ses traitements

L’éditeur de requête SQL permet d’élaborer des requêtes complexes tout en gardant les références aux objets. Ainsi il n’y a pas besoin de coder les clauses « where », « group by » ou « having » comme dans les autres ETL, et l’analyse d’impact se fait à la colonne …

Quelques astuces :

  • simuler un MINUS – je vais faire un tuto dessus bientôt …

En conclusion :
Pour moi Sunopsis/ODI fait partie des meilleurs ETL du marché, il se démarque de ses concurrents principalement par ses performances et par l’intégration des process habituels d’alimentation dans l’outil.

Enquête Gartner : Les utilisateurs jugent les éditeurs de BI et leurs plates-formes

Un article intéressant sur le site du grand bi :

L’enquête Gartner incendie pour une fois les grands éditeurs comme SAP/BO, Oracle ou IBM sur les problèmes remontés par les utilisateurs …
Certes, on pourra critiquer ces résultats en supposant que le nombre de problèmes est aussi fonction du nombre d’utilisateurs – et comme peu de monde dans l’entreprise utilisent les produits gagnants de l’enquête – qui utilise Tableau Software ?
Mais c’est une avancée …

Recette avec les stats d’Oracle

Voici un petit moyen de tester rapidement une table en recette.

Un des tests « génériques » pour voir si une colonne est bien chargée est de voir :
– si toutes les valeurs de la colonne ne sont pas nulles
– si on a des valeurs différentes dans la colonne

Pour cela, on peut écrire 2, voire une seule requête.
Par contre, si on a plusieurs colonnes, il faut soir écrire plusieurs requêtes, soit une seule requête très complexe.

Un autre moyen est d’utiliser les stats d’Oracle, qui vont effectuer ces calculs pour nous !

Tout d’abord, il faut calculer les stats ( attention, je dis bien calculer, et non estimer ) :

-- ( Oracle 10g )
analyze table &TABLE.&OWNER compute statistics;

Ensuite il suffit de requêter la table des stats :

SELECT
  column_name,  
  num_distinct "nb val distinctes",  
  num_nulls "nb val nulles",
  sample_size "nb lignes"
FROM all_tab_columns
WHERE table_name='&TABLE' and owner='&OWNER'
ORDER by column_id;

Filtrer sur num_nulls>0 ou num_distinct=1 par exemple.

Attention, il ne faut pas oublier après de recetter aussi les données fonctionnellement !!!