Tout d'abord : qu'est-ce qu'un orphelin ? Il s'agit d'une clé dans notre table de fait qui arrive de notre système source, mais qui n'est pas référencée dans la dimension associée. Comment cela peut-il se produire ? Plusieurs hypothèses sont possibles : une erreur à la saisie lors d'une gestion par saisie manuelle d'un code, des systèmes de gestions indépendants n'ayant pas des mises à jours simultanées, ... Les causes peuvent être multiples.
Dans les exemples qui suivent on va partir d'une table de faits de ventes qui contient un code client qui n'est pas dans la dimension client (l'exemple n'est pas innocent, c'est un cas rencontré chez un client. La création de la carte client remontait dans les systèmes sources avec une latence d'une quinzaine de jours alors que la vente était bien saisie sur la carte non encore créée)
On a donc en tables sources les tables suivantes :
Une table source Client :
Code Client | Nom | Prénom | … |
12 | Pierre | Jean | |
15 | Dupont | Jacques | |
25 | Martin | Louis |
Une table source Ventes :
DateVente | CodeClient | CodeProduit | Quantité | … |
12/12/11 | 12 | FR1234 | 2 | |
12/12/11 | 12 | FR3421 | 5 | |
13/12/11 | 25 | GR0987 | 10 | |
15/12/11 | 40 | RF5483 | 9 |
qui contient bien un client non référencé (ici le CodeClient 40)
1ère méthode : Le rejet
La première méthode est la plus simple : elle consiste à dire que cette ligne de ventes avec un client inconnu est une anomalie, et à rejeter de ce fait la ligne.
Attention, il faut penser à insérer la ligne rejetée dans une table de rejet pour pouvoir retenter une intégration une fois notre système source client mis à jour.
On a donc au final les 3 tables suivantes :
Une dimension Client :
IdClient | CodeClient | Nom | Prénom | … |
1 | 12 | Pierre | Jean | |
2 | 15 | Dupont | Jacques | |
3 | 25 | Martin | Louis |
Une table de faits Ventes :
IdDate | IdClient | IdProduit | Quantité | … |
20111212 | 1 | 1 | 2 | |
20111212 | 1 | 2 | 5 | |
20111213 | 3 | 3 | 10 |
Et une table de rejet :
DateVente | CodeClient | CodeProduit | Quantité | … |
15/12/11 | 40 | RF5483 | 9 |
Cette méthode est une des plus simples à mettre en place. Il faut juste penser à rejouer l'intégration des lignes de la table de rejet de manière régulière.
2ème méthode : Création d'un membre inconnu
La méthode vue précédemment a un inconvénient : à un instant t, on peut avoir au niveau global des différences de chiffres. En effet des lignes sont rejetées, ce n'est pas la meilleure manière de gérer l'intégrité des données.
La solution consiste donc à définir un client inconnu sur lequel on rattachera les lignes contenant un code client absent du système source.
On crée donc un client inconnu dans notre nouvelle table de dimension Client (souvent en id -1, ligne que l'on créera une bonne fois pour toutes au moment de la création de la table) :
IdClient | CodeClient | Nom | Prénom | … |
-1 | N/A | N/A | N/A | |
1 | 12 | Pierre | Jean | |
2 | 15 | Dupont | Jacques | |
3 | 25 | Martin | Louis |
Et au moment du chargement de notre table de faits Ventes, on met comme IdClient -1 lorsqu'on trouve un client non présent dans la table de dimension :
IdDate | IdClient | IdProduit | Quantité | … |
20111212 | 1 | 1 | 2 | |
20111212 | 1 | 2 | 5 | |
20111213 | 3 | 3 | 10 | |
20111215 | -1 | 4 | 9 |
Cette méthode est la plus répandue sur les projets décisionnels. Elle a cependant un inconvenient majeur, c'est qu'on a une perte d'information. Si le client est créé ultérieurement notre ligne sera toujours rattaché au client inconnu dans notre table de faits.
Pour cela, on peut utiliser une variation de cette deuxième méthode (méthode 2bis) qui consiste à rajouter dans notre table de faits le CodeClient afin de pouvoir mettre à jour l'IdClient une fois le client créé dans le système source.
La table de faits Ventes ressemblerait donc à :
IdDate | IdClient | CodeClient | IdProduit | Quantité | … |
20111212 | 1 | 12 | 1 | 2 | |
20111212 | 1 | 12 | 2 | 5 | |
20111213 | 3 | 25 | 3 | 10 | |
20111215 | -1 | 40 | 4 | 9 |
Cela nécessite comme la première méthode le passage d'un script de mise à jour que l'on planifierait par exemple toutes les semaines ou tous les mois.
Je n'aime pas trop cette variation car elle crée dans la table de faits des données qui n'ont pas grand chose à y faire.
3ème méthode : la méthode "ultime"
La dernière méthode empêche toute perte d'informations mais peut être coûteuse en performance.
Elle consiste à scanner en amont du chargement de la table de faits les codes client non présents dans la table de dimension, et à les insérer dans la table de dimension, avec des attributs neutres qui seront mis à jour lors de l'arrivée du client dans le système source.
On obtient alors la table de dimension suivante :
IdClient | CodeClient | Nom | Prénom | … |
1 | 12 | Pierre | Jean | |
2 | 15 | Dupont | Jacques | |
3 | 25 | Martin | Louis | |
4 | 40 | Inconnu | Inconnu |
Le nom inconnu et le prénom inconnu seront mis à jour lors de l'arrivée dans le système source du client ayant le CodeClient 40.
Et notre chargement de la table de faits donne la table suivante :
IdDate | IdClient | IdProduit | Quantité | … |
20111212 | 1 | 1 | 2 | |
20111212 | 1 | 2 | 5 | |
20111213 | 3 | 3 | 10 | |
20111215 | 4 | 4 | 9 |
Cette méthode est la plus robuste (d'où le nom "ultime") dans le sens où vous pouvez alimenter votre table de faits sans lancer l'alimentation de votre table de dimension et ne pas perdre d'informations.
Conclusion :
Le méthode 2bis et 3 sont les plus robustes en terme de conservation de l'information. En revanche, elles n'ont d'intérêt que dans le cas où on a une chance de recevoir ultérieurement le client dans le système source. Dans les faits, ce sont la méthode 2 et dans une moindre mesure la méthode 3 qui sont les plus utilisées sur les projets.
Gardez à l'esprit que la gestion des orphelins doit se faire en fonction du souhait de votre client car il s'agit avant tout d'une problématique fonctionnelle. Ce n'est pas au développeur de décider quelle méthode implémenter, mais c'est à lui d'informer son client quand aux différentes gestions possibles.
Aucun commentaire:
Enregistrer un commentaire