BI experience - Part 2

Copier une base de données vers une autre avec Talend

25 août 2011

Depuis la version 4.1.2, Talend a sortie une option assez remarquable :le Dynamic Schema

Je vous propose dans ce post de détailler la démarche que nous avons adoptée pour l‘alimentation de notre infocentre : copie des différentes bases de données de la société à partir desquelles le datawarehouse est alimenté.

Un simple job sera réalisé pour amener les données d’une base de données source vers une base de données cible :
job_fils

Voici l’option en question que vous pourrez utiliser dans votre input:

option_dynamic_schema2

Et si vous avez des règles de gestion à ajouter n’hésitez pas avec le tJavaFlex :
action_sur_lignes1

/**l’exemple de traitement en plus lisible…**/
for(int i = 0; i < row3.dyn_Col.metadatas.size(); i++) {
row3.dyn_Col.metadatas.get(i).setName(row3.dyn_Col.metadatas.get(i).getName().toLowerCase());
}

Ce job, décrit ci-dessus, est appelé par un job père qui lui donne le contexte contenant le nom de la table courante à migrer :

job_pere

Une variable de context est passée au sous job (monsousjobcopie) : my_current_table

L’input requête sur une table de paramétrage. En effet nous n’avons pas forcement besoin de toutes les tables de toutes les bases de données. Donc à travers une table de paramétrage nous choisisson celle que l’on veut migrer :

input_job_pere

Ce job père appelle aussi un autre sous job qui lui va permettre de migrer les indexes :
index

Donc pour chaque table on fera un appel à une routine (code qu’il y a dans le tJava):

routines.IndexMigrer.migrate_index(((java.sql.Connection)globalMap.get(”conn_tMSSqlConnection_2″)), ((String)globalMap.get(”current_TABLE.nom_table”)), ((java.sql.Connection)globalMap.get(”conn_tPostgresqlConnection_4″)),context.Cible_Schema + (String)globalMap.get(”schema”) + “.” +
((String)globalMap.get(”current_TABLE.nom_table”)));

Et en bonus voici la routine que nous avons créés qui selon la base de données (Oracle, Posgres, SQL Server 2000 ou SQL Server 2005) va requêter dans la bonne table système :

/***************Routines migration indexes ************************/

public class IndexMigrer {
public static void migrate_index(Connection org_connect, String org_nomtable,
Connection dest_connect, String dest_nomtable)  throws java.sql.SQLException
{
if(org_connect.getMetaData().getDatabaseProductName().equalsIgnoreCase(”Microsoft SQL Server“) )
{
Statement stat = org_connect.createStatement();
ResultSet rs;
if(org_connect.getMetaData().getDatabaseMajorVersion()==9)
{
rs=stat.executeQuery(”SELECT IDX.name as index_name, COL.name as column_name FROM sys.index_columns IDXC”
+” INNER JOIN sys.objects OBJ”
+” ON IDXC.object_id = OBJ.object_id”
+” INNER JOIN sys.schemas SCH”
+” ON SCH.schema_id = OBJ.schema_id”
+” INNER JOIN sys.indexes IDX”
+” ON (IDXC.object_id = IDX.object_id AND IDXC.index_id = IDX.index_id)”
+” INNER JOIN sys.columns COL”
+” ON (IDXC.column_id = COL.column_id AND OBJ.object_id = COL.object_id)”
+” where OBJ.name=\’”+org_nomtable+”\’”
+” ORDER BY OBJ.name” );
}
else
{
rs=stat.executeQuery(”select i.name as index_name,c.name as column_name”
+” from sysindexkeys as indk”
+” inner join sysindexes as i on”
+” (indk.indid=i.indid and indk.id=i.id )”
+” inner join syscolumns as c on”
+” (indk.colid=c.colid and indk.id=c.id )”
+” inner join sysobjects as o on”
+” (indk.id=o.id)”
+” and o.name=\’”+org_nomtable+”\’ ”
+” ORDER BY o.name” );
}
Map m =new HashMap();
Map m_key=new HashMap();
while(rs.next())
{
if(!m.containsKey(rs.getString(1)))
{
List l = new ArrayList();
l.add(rs.getString(2));
m.put(rs.getString(1),l);
m_key.put(rs.getString(1), rs.getString(1));
}
else if(m.containsKey(rs.getString(1)))
{
List l=(List)m.get(rs.getString(1));
l.add(rs.getString(2));
m.put(rs.getString(1),l);
}
}
StringBuffer sb=new StringBuffer();
for (Iterator i = m.keySet().iterator() ; i.hasNext();){
String key = (String)i.next();
sb.append(”CREATE INDEX “);
sb.append(”IDX_”+key);
sb.append(” ON “+dest_nomtable+” (”);
List l=(List)m.get(key);
for(int j=0;j<l.size();j++)
{
sb.append(l.get(j));
if(j!=l.size()-1)
sb.append(”,”);
}
sb.append(”);\n”);
}
try{
Statement bla=dest_connect.createStatement();
System.out.println(”"+sb.toString());
bla.execute(sb.toString());
}
catch (java.sql.SQLException e)
{
//System.out.println(dest_nomtable);
System.out.println(e.getMessage());
}
dest_connect.commit();
//System.out.println(dest_nomtable);
}
if(org_connect.getMetaData().getDatabaseProductName().equalsIgnoreCase(”PostgreSQL“))
{
Statement stat = org_connect.createStatement();
ResultSet rs=stat.executeQuery(”SELECT indkey as colonne_index,pci.relname as nom_index,pct.relname as nom_table from pg_index as pi”
+” , pg_class as pci, pg_class as pct ”
+” where pci.oid=pi.indexrelid”
+” and pct.oid=pi.indrelid and pct.relname  not like ‘pg_%’ and pct.relname=’”+org_nomtable+”‘ ” );
while( rs.next())
{
String s=rs.getString(1);
java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(s, ” “);
List <Integer> num_columns=new ArrayList();
while ( tokenizer.hasMoreTokens() ) {
num_columns.add(Integer.parseInt(tokenizer.nextToken()));
}
Statement sel=org_connect.createStatement();
ResultSet rsset=sel.executeQuery(”SELECT * from “+org_nomtable+” LIMIT 1″);
StringBuffer sb=new StringBuffer();
sb.append(”CREATE INDEX “+rs.getString(2)+” ON “+dest_nomtable+” (” );
Iterator i=num_columns.iterator();
while(i.hasNext())
{
sb.append(rsset.getMetaData().getColumnLabel((Integer)i.next()));
if(i.hasNext())
sb.append(”,”);
}
sb.append(”) ;\n”);
Statement bla=dest_connect.createStatement();
bla.execute(sb.toString());
dest_connect.commit();
bla.close();
}
}
if(org_connect.getMetaData().getDatabaseProductName().equalsIgnoreCase(”Oracle“))
{
Statement stat = org_connect.createStatement();
ResultSet rs=stat.executeQuery(”SELECT col.index_name,col.column_name FROM all_indexes cons INNER JOIN all_ind_columns col ON cons.owner = col.index_owner AND cons.index_name = col.index_name WHERE OWNER = ‘AEFE’ AND cons.table_name=\’”+org_nomtable+”\’” );
Map m =new HashMap();
Map m_key=new HashMap();
while(rs.next())
{
if(!m.containsKey(rs.getString(1)))
{
List l = new ArrayList();
l.add(rs.getString(2));
m.put(rs.getString(1),l);
m_key.put(rs.getString(1), rs.getString(1));
}
else if(m.containsKey(rs.getString(1)))
{
List l=(List)m.get(rs.getString(1));
l.add(rs.getString(2));
m.put(rs.getString(1),l);
}
}
StringBuffer sb=new StringBuffer();
for (Iterator i = m.keySet().iterator() ; i.hasNext();){
String key = (String)i.next();
sb.append(”CREATE INDEX “);
sb.append(”IDX_”+key);
sb.append(” ON “+dest_nomtable+” (”);
List l=(List)m.get(key);
for(int j=0;j<l.size();j++)
{
sb.append(l.get(j));
if(j!=l.size()-1)
sb.append(”,”);
}
sb.append(”);\n”);
}
Statement bla=dest_connect.createStatement();
System.out.println(”"+sb.toString());
bla.execute(sb.toString());
dest_connect.commit();
}}}

Très important, si un problème de typage persiste n’hésitez pas à modifier les fichiers de mapping dans :

fichier_mappingCes fichiers sont utiles et simples à utiliser puisqu’ils permettent de connaitre les transformations de typage. En gros voici comment procède Talend :

typage BDD source => typage JAVA => typage BDD cible

Exemple d’utilisation :

ma base de données source est SQL server et ma base de données cible est postgres  :

La démarche sera donc d’aller dans  MSSQL_mapping.xml  et de regarder la rubrique : <dbToTalendTypes> pour voir en quel type Java les typages de ma base de données MSSQL seront transformés. Ensuite il faudra regarder dans postgres_mapping.xml pour regarder les typages par défault que propose Talend dans la rubrique  <talendToDbTypes> pour la retransformation des types JAVA en typages postgres.

Vous pourrez ainsi personnaliser ces transformations.

Si ces fichiers sont modifiés il faudra bien sur les répercutés sur tous les clients  TIS  et sur le serveur  dans les workspaces dans:

  • .JAVA > src > xmlMappings
  • et dans .JAVA > classes > xmlMappings

J’espère que ce post vous aura permis de voir les possibilités qu’offrent la solution Talend pour ce genre de besoin.

N’hésitez pas à poster pour donner votre opinion!

Bonne Année 2011

5 janvier 2011

Je vous souhaite à tous une excellente année 2011 sur le plan professionnel mais aussi personnel.

L’année 2010 aura été riche en évènements. J’espère que mes posts auront pu en aider certains dans leur travail…

Voici les chiffres clefs  de la vie de ce blog, (source des informations : Xiti et Feedburner) il y a eu en moyenne entre 100 et 150 visites par jour sur l’année 2010 . Une vingtaine d’articles ont été publiés et une cinquantaine de commentaires ont été postés.

Je voudrai vous remercier pour tous vos commentaires, ils m’encouragent vraiment à continuer de partager mes connaissances avec vous…

Cela fait maintenant 2 mois que je n’ai pas posté faute de temps mais je ne vous oublie pas!

Merci encore de faire vivre ce blog! Et à bientôt!

Industrialiser son datawarehouse

8 octobre 2010

Comment rechargez-vous, ou rafraichissez-vous votre datawarehouse? Quelle est votre méthode d’industrialisation afin que la plateforme de production puisse offrir des données à jour aux utilisateurs finaux?

Voici la méthodologie utilisée dans mon projet :

1 - Pointer les bases de données sources des datamarts => il faudra séparer les datamarts en fonction afin que s’il y est un problème sur l’une des bases de données sources cela n’impacte pas d’autres datamarts non liés à cette source.

2 - Lister les dimensions et les datamarts qu’elles touchent => si une dimension est rechargée il faudra recharger les faits concernés en conséquence

3 - Identifier les fréquences de chargement pour rassembler les faits ou dimensions qui devront être rafraichis en même temps

4 - Etablir l’ordre dans lequel les dimensions et faits doivent être remplis

En fonction des ces 4 points il se dégage deux visions :

- une vision faits => en fonction de la base de données, de la fréquence, de l’ordre de chargement il faudra créer des blocs de faits qui seront ensuite schedulés en évaluant le temps de chargement de chaque blocs

- une vision dimensions/faits => dès qu’une dimension est rechargée il faudra recharger les faits qu’elle touche. Lors du scheduling il faudra aussi évaluer le temps de chargement de ces blocs dimensions/faits

La représentation sous forme de schémas peut vraiment aider…

Ce scheduling est donc fait pour les jobs de production sur le datawarehouse de production. La fenêtre de temps d’exécution de cet industrialisation doit quand même être bien évaluée car si juste avant vous avez l’alimentation de votre infocentre (copie des bases de données sources) lui même lancer après les actions de backup, restore des bases de données sources…Vous imaginez que tout ça doit être prévu assez précisement.

Et vous comment faites vous?

Le leader mondial Business Object

6 octobre 2010

Précédemment je vous ai décrit un certain nombre de logiciels plutôt orientés “open source”. Dans ce post, je voudrai m’attarder sur l’offre du leader mondial “Business Object”. J’ai assisté à une petite présentation du produit version webi XI 3.1, je voulais donc vous faire partager la vision de la solution que j’ai pu percevoir.

Tout d’abord, il faut savoir que Business Object est un portail qui à la base permet de faire du suivi d’activité en se plugant directement sur les bases de productions qu’à l’entreprise…Je pense qu’on a tous entendu parlé de la force de BO : son univers. L’univers de BO est une couche sémantique qui ne contient pas de données : c’est une représentation métier de l’information. Le développeur aura accès au designer pour le construire. A partir des tables du datawarehouse, ou des bases de données sources, une interface graphique aidera  à créer la requête qui constituera l’univers.

Le développeur construira des univers en respectant les bonnes pratiques :

  • création des contextes : permet d’optimiser les requêtes SQL en indiquant le chemin le plus court selon la table de fait que l’on interroge.  Si par exemple on fait appelle à plusieurs tables de faits ayant des dimensions communes pour éviter les boucles
  • création de raccourcis jointures : permet de lui indiquer le chemin le plus court en fonction des id des tables : exemple table1 a un id_pays table2  a un id_departement et table3 id_ville  si dans table1 il y a aussi un id_ville, on lui indiquera de passer directement de table1 à table3).

A partir de cet univers, l’utilisateur final pourra créer sa propre requête dans la plateforme Infoview de BO. Le résultat de cette requête sera assimilé à un petit cube de données où les données seront chargées à l’intérieur. A travers ce cube de données, il pourra construire son rapport en utilisant plusieurs techniques :

  • rupture : créé un tableau par valeurs de données choisies pour faire une rupture
  • section : met des titres par valeurs de données choisi pour faire une section
  • en permettant aux autres utilisateurs de l’interactivité sur le rapport (multiview de l’information)

Afin que la création du rapport ne soit pas trop lourde, l’interface pourra être en HTML au lieu d’être en JAVA. Donc en cas de réseau limité, l’interface sera quand même efficace.

La solution BO ne fait pas le cube OLAP, néamoins elle permet de créer une navigation en mode exploration des données. C’est finalement le développeur qui devra créer un rapport qui permettra cette exploration. Le concept de l’interface du cube plier/déplier des informations n’existent donc pas dans BO.

Une brique étonnante de BO est Xcelsius : ce module transforme une feuille Excel en document Flash. Pour être plus précise le document Flash se base sur une feuille Excel et cette dernière rapatrie les données de la base de données avec un appel de webservice. Le document Flash utilisera la feuille Excel comme une base de donnée. Pour générer le webservice qui va permettre de rapatrier les données (ou cette URL http), cette requête pourra être créée par une autre brique de BO : “query as webservice“. Dans cette représentation Flash de l’information, on poura même y mettre un peu de cartographie en descendant jusqu’au niveau du pays. Xcelsius peut être utilisé pour faire des tableaux de bords ou de la simulation. Le résultat peut vraiment être joli.

La solution BO permet aussi de faire aussi du publipostage en poussant l’information vers les utilisateurs dans leur boite mail ou sur un répertoire particulier.

Je ne suis bien sur pas exhaustive sur cette présentation. C’est un aperçu de ce que peut offrir cette solution.

Mon ressentie est que Business Object est une solution aboutit mais les technologies utilisées paraissent un peu lourdes et pas très sexy en comparaison avec d’autres logiciels vu et décrit dans précédent post. Néanmoins c’est quand même le leader mondial, il a fait ses preuves.

Et vous, êtes-vous utilisateur ou développeur BO…Que pensez vous de cet outil?

Présentation de Qlikview

12 juillet 2010

Société suédoise, Qlikview a créé la première version du logiciel éponyme en 1995. Ce n’est qu’en Septembre 2007 qu’ils ont ouvert des bureaux en France.

qlikview_logo

Leur slogan est ” click and view” . L’originalité de leur offre réside dans la manière de se déplacer dans les données. D’après Qlikview l’utilisateur se promène dans les données par “association d’idées”.

Exemple : “J’ai oublié mon cahier chez quelqu’un. Généralement, Je ne me souviens pas directement de la date, de l’heure et du lieu de l’oubli. Mais je vais plutôt penser à un laps de temps cela fait 2 jours que je ne l’ai pas utilisé. Et la dernière fois que je l’ai utilisé c’était chez la personne X que j’ai vu à telle heure et à tel endroit”. Donc par association d’idées je suis remontée à la donnée qui m’intéressait.”

Afin de présenter ce cheminement d’association d’idées, les applications car sous Qlikview on ne parle pas de rapport mais d’application, proposent un code couleur (qui peut être personnalisé)

  • vert représente la question posé (exemple : je clique sur la première dimension pays et plus précisement sur allemagne car je me pose une question sur ce pays et puis je clique sur la dimension type de magasin)
  • gris sera les résultats qui ne répondent pas à ma question. (liste des types de produits que ne propose pas ce type de magasin)Ce type de résultat peut vraiment être utilise lors d’une analyse. Cette solution est vraiment atypique pour les rapports que l’on peu construire classiquement et peut être d’une grande aide pour l’analyse.
  • Blanc représente la réponse

Leurs applications sont basées sur les principes de Google avec la possibilité de faire des recherches facilement et instantanément dans les applications pour faire une analyse ciblée. De plus les objets utilisés dans les applications s’utilisent comme des widgets Google. Leurs applications sont vraiment orientées web.  En exemple concret, pour enregistrer une application  avec des paramètres qu’on aura choisis spécifiquement, l’utilisateur aura juste a enregistrer ce résultat en ajoutant un favoris.

De l’intéractivité, une possibilité d’autonomie pour les utilisateurs finaux, les applications proposent des multiviews c’est à dire que chaque objet est de type graphique et donc l’utilisateur pourra visualiser les données en tableau puis en camembert puis en histogramme… De plus les résultats des questions des utilisateurs sont instantanés car tous les données sont montées en mémoire en s’appuyant sur une base de données vectorielle propre a Qlikview qui stocke les données  sous un format compressé.  Cette solution peut vraiment répondre à des entreprises qui ont une problématique de volumétrie. Les fichiers de BDD sont sous format .qvd.

Par contre il faut savoir que cette application ne propose pas de portail collaboratif. c’est plutôt une application qui a pour vocation a être intégrée dans un autre portail. En dernier détail technique, QlikView est une application qui s’installe sur du windows aussi bien pour les serveurs que pour les applications locales. Si vous avez un besoin d’avoir accès aux données en déconnecter, il faudra avoir l’application Qlikview en local sur votre poste pour ouvrir les applications.

Afin d’être toujours plus productif et pour être force de proposition, lors du téléchargement de QlickView sur leur site des exemples d’applications sont proposées pour données des idées aux développeurs.

Vous pouvez dès à présent tester ce logiciel en téléchargeant la version communautaire. La particularité de cette version est que vous  vous allez installer cette application  en local sur votre poste. Vous pourrez télécharger des applications qui pourront être visualiser via un navigateur par les utilisateurs. Par contre vous ne pourrez pas échanger des applications avec d’autres développeurs ou utilisateurs car elles seront criptées pour n’être utilisables uniquement sur votre poste. Ce n’est que lors de l’achat d’une licence que ces applications seront débloquées.

Concernant les prix des formations. Il est conseillé d’en prendre 4 jours :

  • 2 jours pour apprendre à utiliser qlikview designer pour construire les applications
  • 2 jours pour apprendre le script c’est à dire ce qui ramène les données à l’application

Le coût d’une formation dans les locaux de Qlikview est de 650€/jour/pesonne. La mise en oeuvre de cette solution ne sera jamais faite par l’éditeur lui même mais par ses sociétés de services partenaires ou la journée sera facturée 1000€/jour/intervenant.

La solution est vendue par application par utilisateur : 250€/application/utilisateur. Et pour une utilisation illimitée d’applications par utilisateur est de 960€/utilisateur

Les prix annoncés sont bien sûr des prix publics. En espérant vous avoir donné assez d’informations pour vous donnez l’envie d’aller creuser ce logiciel plus en avant.