IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Optimisations SGBD Discussion :

Structure hiériarchique à optimiser (la rendre évolutive)


Sujet :

Optimisations SGBD

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 8
    Points : 0
    Points
    0
    Par défaut Structure hiérarchique à optimiser (la rendre évolutive)
    Bonjour,

    J'ai développé une base de donnée basée sur une structure hiérarchique (l'application est développée sur un modele composite) et je cherche à résoudre plusieurs problèmes :

    - Comment limiter au maximum la dépendance entre mes différentes tables : je veux pouvoir ajouter des noeuds intermédiaires facilement et également changer l'ordre de dépendance.

    - Comment optimiser la performance d'une telle relation : création de vues ou simples jointures ?

    La situation
    ------------


    - toutes mes tables sont liées les unes autres par une relation parentID :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Table1 (idT1, desc)
    Table2(idT2, desc, ..., Table1ID)
    Table3(idT3, desc, ..., Table2ID)
    ...
    Table8(idT8, desc, ..., Table7ID)
    - on peut lier plusieurs tables à une seule :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Table6(idT6,desc, ..., Table5ID)
    Table7(idT7,desc, ..., Table5ID)
    Objectif
    ----------


    Limiter la dépendance :
    J'aimerai, par exemple, ajouter facilement une tableX entre mes tables 2 et 3. Cela me demande donc d'effectuer quelques débranchements/rebranchements... ce que je cherche à éviter.
    En clair, je cherche une solution pour externaliser l'ordonnancement de mes tables.
    Une solution serait peut-être d'utiliser une table de gestion "OrdreTable" dans laquelle on aurait les champs :
    id, parentID, table_name

    Cette table contiendrait donc les différentes relations entre tables, exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    1, NULL, Table1
    2, 1, Table2
    3, 2, Table3
    4, 2, Table4 (ici j'attache ma Table4 à la table2)
    ...
    Et dans chacune des tables on aurait un champ "parentId" (champ qui pointe sur la table définit par "OrdreTable")
    Cela dit, je ne sais pas si c'est la meilleure solution.... d'où mon message.


    Merci d'avance

    edit : un internaute évoque ce problème (sans solution) : http://forums.mysql.com/read.php?125...741#msg-154741
    (différence : je ne gère pas les champs "child" mais le problème est le même)

    il existe des tutoriaux sur ce fameux modèle "data-driven join table" ?

  2. #2
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    7 945
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 7 945
    Points : 30 716
    Points
    30 716
    Billets dans le blog
    16
    Par défaut
    Ce genre de traitement de la hiérarchie vous convient-il (SQL Server 2005) ?


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Create table MaTable (  
        TableId     Integer      Not Null
      , TableNom    Varchar(48)  Not Null 
     , Constraint T1 Primary Key (TableId)
    ) ;
     
    Create table Hierarchie (
        TableId     Integer      Not Null
      , ParentId    Integer      Not Null
     , Constraint H1 Primary Key (TableId)
     , Constraint H2 Foreign Key (TableId) References MaTable
            On delete Cascade
     , Constraint H3 Foreign Key (ParentId) References MaTable
            On delete No Action
     , Constraint H4 Check (ParentId <> TableId)
    ) ;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Insert Into MaTable Values (1, 'TABLE 1') 
    Insert Into MaTable Values (2, 'TABLE 2') 
    Insert Into MaTable Values (3, 'TABLE 3') 
    Insert Into MaTable Values (4, 'TABLE 4') 
    Insert Into MaTable Values (5, 'TABLE 5') 
    Insert Into MaTable Values (6, 'TABLE 6') 
    Insert Into MaTable Values (7, 'TABLE 7') 
    Insert Into MaTable Values (8, 'TABLE 8')
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Insert Into Hierarchie Values (2, 1)
    Insert Into Hierarchie Values (3, 2)
    Insert Into Hierarchie Values (4, 2)
    Insert Into Hierarchie Values (6, 5)
    Insert Into Hierarchie Values (7, 5)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Select   x.*, y.TableNom
          , (Select z.TableNom 
             From   MaTable z 
             Where  z.TableId = x.ParentId) As ParenteNom 
    from Hierarchie x Inner join MaTable y ON x.TableId = y.TableId
    =>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    TableId    ParentId    TableNom
       2          1         table 2
       3          2         table 3
       4          2         table 4
       6          5         table 6
       7          5         table 7
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  3. #3
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 8
    Points : 0
    Points
    0
    Par défaut
    Merci,

    je réfléchis en terme de perf (pour faire les jointures) sachant que j'ai une dizaine de tables contenant chacune des dizaines de milliers de lignes....

  4. #4
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 8
    Points : 0
    Points
    0
    Par défaut
    Le problème avec ton modèle c'est qu'on perd la hiérarchie des données.

    J'avais pensé à un modèle (sur 2 niveaux) comme (pas forcement la bonne syntaxe) :

    //l'idée est de créer une table Hiérarchie qui contient l'arborescence des données des différentes tables.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CREATE TABLE Table1 (  
        Id     Integer AUTO_INCREMENT     NOT NULL
      , Parent_ID Integer       NOT NULL,
     , DESC VARCHAR(10) NULL
     , Constraint T1 PRIMARY KEY (Id)
     , Constraint T2 FOREIGN KEY (Parent_ID) REFERENCES Hierarchie
    ) ;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CREATE TABLE Table2 (  
        Id     Integer   AUTO_INCREMENT    NOT NULL
      , Parent_ID Integer       NOT NULL 
     , DESC VARCHAR(10) NULL
     , Constraint T1 PRIMARY KEY (Id)
     , Constraint T2 FOREIGN KEY (Parent_ID) REFERENCES Hierarchie
    ) ;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    CREATE TABLE Hierarchie (  
        Id     Integer AUTO_INCREMENT     NOT NULL
      , Parent_ID Integer       NOT NULL ,
      , TableINFO VARCHAR(60)
     , Constraint T1 PRIMARY KEY (Id)
     , Constraint T2 FOREIGN KEY (Parent_ID) REFERENCES Hierarchie 
    ) ;

    //ajout d'une donnée dans ma table1
    //pas de niveau supérieur donc NULL à parent_id
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    INSERT INTO Hierarchie(id, parent_id, TAbleINFO) VALUES('', NULL, Table1)
    ID_T1 = "SELECT LAST_INSERT_ID";
    INSERT INTO Table1(id, parent_id, desc) VALUES('', ID_T1, "Desc...");
    //ajout d'une donnée (dans Table2) liée à ma précédente donnéee ajoutée dans la Table1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    INSERT INTO Hierarchie(id, parent_id, TAbleINFO) VALUES('', ID_T1, Table2)
    ID_T2 = "SELECT LAST_INSERT_ID";
    INSERT INTO Table1(id, parent_id, desc) VALUES('', ID_T2, "Desc2...");

    et ainsi de suite....

    Au final, je me retrouve avec une table hierarchie qui contient un nombre d'enregistrement égal au nombre d'enregistrement de ma table1 + celui de ma table2.

    Je sais pas si y a un moyen plus propre pour gérer ce genre d'architecture...

  5. #5
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    7 945
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 7 945
    Points : 30 716
    Points
    30 716
    Billets dans le blog
    16
    Par défaut
    Citation Envoyé par Greg221 Voir le message
    Le problème avec ton modèle c'est qu'on perd la hiérarchie des données
    Qu’entendez-vous par perdre la hiérarchie des données ?
    Je ne sais pas si votre SGBD traite de la jointure récursive, mais selon la norme SQL, DB2, ou encore SQL Server, il n’y aucun problème.
    Je reprends ici le jeu d’instructions que je vous ai déjà proposé :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Create table MaTable (  
        TableId     Integer      Not Null
      , TableNom    Varchar(48)  Not Null 
     , Constraint T1 Primary Key (TableId)
    ) ;
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Create table Hierarchie (
        TableId     Integer      Not Null
      , ParentId    Integer      Not Null
     , Constraint H1 Primary Key (TableId)
     , Constraint H2 Foreign Key (TableId) References MaTable
            On delete Cascade
     , Constraint H3 Foreign Key (ParentId) References MaTable
            On delete No Action
     , Constraint H4 Check (ParentId <> TableId)
    ) ;

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Insert Into MaTable Values (1, 'table 1') 
    Insert Into MaTable Values (2, 'table 2') 
    Insert Into MaTable Values (3, 'table 3') 
    Insert Into MaTable Values (4, 'table 4') 
    Insert Into MaTable Values (5, 'table 5') 
    Insert Into MaTable Values (6, 'table 6') 
    Insert Into MaTable Values (7, 'table 7') 
    Insert Into MaTable Values (8, 'table 8')

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Insert Into Hierarchie Values (2, 1)
    Insert Into Hierarchie Values (3, 2)
    Insert Into Hierarchie Values (4, 2)
    Insert Into Hierarchie Values (5, 3)
    Insert Into Hierarchie Values (6, 5)
    Insert Into Hierarchie Values (7, 5)

    Pour retrouver la descendance de la table pour laquelle ParentId vaut i (i = 1 dans l'exemple ci-dessous) :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    With Vue (Descendante, Ascendante) As 
        (
         Select TableId, ParentId 
         From   Hierarchie  
         Where  ParentId = 1  
        UNION ALL 
         Select I.TableId, I.ParentId  
         From   Vue, Hierarchie As I 
         Where  I.ParentId = Vue.Descendante 
        )
     Select Ascendante, Descendante From Vue 
    ;

    Résultat des opérations :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Ascendante   Descendante
        1             2
        2             3
        2             4
        3             5
        5             6
        5             7
    Ce résultat ne ressemble-t-il pas à une hiérarchie ? Qu’a-t-on perdu ?
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  6. #6
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    7 945
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 7 945
    Points : 30 716
    Points
    30 716
    Billets dans le blog
    16
    Par défaut
    Citation Envoyé par Greg221 Voir le message
    Je réfléchis en terme de perf (pour faire les jointures) sachant que j'ai une dizaine de tables contenant chacune des dizaines de milliers de lignes....
    Concernant Oracle, la jointure récursive est traitée sous une forme différente(clause Connect by), mais j'ai observé une performance excellente (100 millisecondes pour extraire une nomenclature, dans une table de 500000 lignes), dans un secteur où l’on ne rigole pas avec les nomenclatures, à savoir celui de la grande distribution.

    Et bien sûr avec la structure que je vous ai proposée et qui est un classique depuis bien des années.

    Rien ne vous interdit de faire des tests à votre tour.
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  7. #7
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    7 945
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 7 945
    Points : 30 716
    Points
    30 716
    Billets dans le blog
    16
    Par défaut
    Bonsoir,


    Citation Envoyé par Greg221 Voir le message
    J'avais pensé à un modèle (sur 2 niveaux), l'idée est de créer une table Hiérarchie qui contient l'arborescence des données des différentes tables.
    Votre problème présente en fait une particularité, car si je comprends bien, la table que j’ai appelée MaTable est en réalité l’union de plusieurs tables : MaTable1, MaTable2, etc. Comme vous le laissez entendre, une solution pour se ramener à une situation connue, pourrait consister à procéder à une factorisation, en ajoutant "un niveau". On pourrait par exemple conserver les tables MaTable et Hierarchie que j’ai proposées, et mettre la première en relation avec MaTable1, MaTable2, etc. Il faudrait alors mettre en œuvre une colonne TableId pour chacune de ces dernières, de manière à établir une référence vers MaTable selon le mécanisme des clés étrangères.

    Le MLD correspondant est le suivant :


    Dans les tables MaTable1, MaTable2, etc., le losange rougeâtre est le symbole d’une clé étrangère. Outil utilisé : MySQL Workbench (gratuit).

    On conserve donc les tables MaTable et Hierachie telles qu'elles ont été définies dans le message 5, mais on définit en plus les tables MaTable1, MaTable2, etc. :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    Create table MaTable1 (  
        Table1Id      Integer      Not Null
      , Table1Data    Varchar(48)  Not Null 
      , TableId       Integer      Not Null      
     , Constraint MaT1PK Primary Key (Table1Id)
     , Constraint MaT1AK Unique (TableId)
    ) ;
    Create table MaTable2 (  
        Table2Id      Integer      Not Null
      , Table2Data    Varchar(48)  Not Null 
      , TableId       Integer      Not Null      
     , Constraint MaT2PK Primary Key (Table2Id)
     , Constraint MaT2AK Unique (TableId)
    ) ;
    Create table MaTable3 (  
        Table3Id      Integer      Not Null
      , Table3Data    Varchar(48)  Not Null 
      , TableId       Integer      Not Null      
     , Constraint MaT3PK Primary Key (Table3Id)
     , Constraint MaT3AK Unique (TableId)
    ) ;

    On valorise ces tables en cohérence avec MaTable (dont en passant la colonne TableNom peut gicler) :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Insert Into MaTable1 Values (1, 'Table 1, Data 1', 1)
    Insert Into MaTable1 Values (2, 'Table 1, Data 2', 2)
     
    Insert Into MaTable2 Values (1, 'Table 2, Data 3', 3)
    Insert Into MaTable2 Values (2, 'Table 2, Data 4', 4)
    Insert Into MaTable2 Values (3, 'Table 2, Data 5', 5)
     
    Insert Into MaTable3 Values (1, 'Table 3, Data 6', 6)
    Insert Into MaTable3 Values (2, 'Table 3, Data 7', 7)
    Insert Into MaTable3 Values (3, 'Table 3, Data 8', 8)

    Sur la base des colonnes union-compatibles, On crée une vue d'union de ces tables (vue non indispensable, mais qui permet d'y voir plus clair) :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Create View MaTableUnion (UnionId, UnionData, TableId) As
       Select Table1Id, Table1Data, TableId
       From   MaTable1
      Union All 
       Select Table2Id, Table2Data, TableId
       From   MaTable2
      Union All 
       Select Table3Id, Table3Data, TableId
       From   MaTable3 ;

    Et l'on aménage la requête déjà définie dans le message 5 :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    With MaVue (Enfant, Parente, ParenteData) As 
      (
         Select h.TableId, h.ParentId, t.UnionData 
         From   Hierarchie As h Inner Join MaTableUnion As t  
                ON  h.ParentId = t.TableId 
         Where  h.ParentId = 1
        UNION ALL 
         Select i.TableId, i.ParentId, t.UnionData   
         From   MaVue as v Inner join Hierarchie As i
                             On  i.ParentId = v.Enfant 
                           Inner Join MaTableUnion as t 
                             On  i.ParentId = t.TableId
      )
     Select Parente, Enfant, ParenteData, t.UnionData As EnfantData   
     From   MaVue as v Inner Join MaTableUnion as t
            ON  v.Enfant = t.TableId
    ;

    Au résultat :

    Code Résultat : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      Parente     Enfant   ParenteData        EnfantData
         1          2      Table 1, Data 1    Table 1, Data 2
         2          3      Table 1, Data 2    Table 2, Data 3
         2          4      Table 1, Data 2    Table 2, Data 4
         3          5      Table 2, Data 3    Table 2, Data 5
         5          6      Table 2, Data 5    Table 3, Data 6
         5          7      Table 2, Data 5    Table 3, Data 7 

    Du point de vue fonctionnel, approche-t-on de ce que vous recherchez ?
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  8. #8
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 8
    Points : 0
    Points
    0
    Par défaut
    Merci beaucoup, ça répond parfaitement à mon problème.

    Note : on pourrait peut-être se passer de la table "MaTable" et lier "MaTable1,2,3..." à Hierarchie directement ?

    En terme de perf, je dois pouvoir récupérer des arborescences d'une profondeur de 10, le tout pouvant attendre un millier d'éléments (et sachant également que ce type d'extraction est très solicité). Peut-être que récupérer mes data à partir d'une vue n'est pas très conseillé. D'après mes recherches, deux techniques permettent d'améliorer les perf dans ce cas de figure : le nested set model et la solution de la sauvegarde du "path". J'aurai tendance à m'orienter vers la première solution....

  9. #9
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    7 945
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 7 945
    Points : 30 716
    Points
    30 716
    Billets dans le blog
    16
    Par défaut
    Citation Envoyé par Greg221 Voir le message

    on pourrait peut-être se passer de la table "MaTable" et lier "MaTable1,2,3..." à Hierarchie directement ?
    Dans ces conditions, au lieu d’avoir la table MaTable comme seule parente, la table Hierarchie en aurait N : cela induirait autant de colonnes dans Hierarchie pour héberger les N clés étrangères à mettre en œuvre (en effet, une clé étrangère ne peut faire référence qu’à une seule table). En conséquence, les nulls foisonneraient, or le bonhomme NULL est redoutable.

    Par ailleurs, la mise en oeuvre ultérieure d'une nouvelle MaTableX aurait pour conséquence la révision de la structure de la table Hierarchie, au lieu de l'ajout d'un UNION ALL dans la vue.

    La solution que je vous ai proposée est éprouvée, alors qu’avec celle que vous suggérez, vous vous compliqueriez singulièrement la vie.



    Citation Envoyé par Greg221 Voir le message

    En terme de perf, je dois pouvoir récupérer des arborescences d'une profondeur de 10, le tout pouvant attendre un millier d'éléments (et sachant également que ce type d'extraction est très sollicité).
    Je répète ce que j’ai déjà écrit, en ayant pris un exemple significatif :
    Citation Envoyé par fsmrel Voir le message

    Concernant Oracle, la jointure récursive est traitée sous une forme différente (clause Connect by), mais j'ai observé une performance excellente (100 millisecondes pour extraire une nomenclature, dans une table de 500000 lignes), dans un secteur où l’on ne rigole pas avec les nomenclatures et la performance, à savoir celui de la grande distribution.
    En l’occurrence, on atteignait une profondeur de l’ordre de 7, mais avec un nombre de lignes important. D’une manière générale, que l’on utilise DB2 Oracle ou SQL Server, l’extraction ne pose pas de problème de performances quand les bons index sont en place, etc.



    Citation Envoyé par Greg221 Voir le message
    Peut-être que récupérer mes data à partir d'une vue n'est pas très conseillé.
    Si le SGBD commençait par procéder à l’union des N tables constituant la vue, on pourrait avoir des problèmes de performance, mais heureusement, l’optimiseur d’un SGBDR ne procède pas ainsi. Tout d’abord, en codant "UNION ALL" plutôt que "UNION" on évite un tri de dédoublonnage. Ensuite, si les tables MaTable1, MaTable2, ..., MaTableI, ..., MaTableN sont indexées sur la colonne TableId (qui est à chaque fois clé candidate), au pire le SGBD aura 10N accès disque à quelques millisecondes à effectuer avant de récupérer ce dont il a besoin dans MaTableI.

    Je vous conseille donc de faire des tests de performance poussés, en relation avec la solution que je vous propose, et de n’explorer d’autres voies que si la performance n’est pas au rendez-vous.



    Citation Envoyé par Greg221 Voir le message
    D'après mes recherches, deux techniques permettent d'améliorer les perf dans ce cas de figure : le nested set model et la solution de la sauvegarde du "path". J'aurai tendance à m'orienter vers la première solution.
    Ne connaissant pas ces techniques, j’ai sollicité Google avec comme élément de recherche : "nested set model". Le premier article que j’ai trouvé est celui-ci : Trees in SQL - nested set model. L’auteur commence par critiquer le système des tables qui s’auto-référencent : ça n’est effectivement pas ce qu’il y a de mieux pour gérer une hiérarchie, mais avant de proposer sa solution, il avait d’autres voies à explorer et commencer par relire l’article fondateur de Codd, page 379.

    Quant à dire que la table qu’il met en cause n’est pas normalisée, il faudrait qu’il précise quelle forme normale est violée : il est sorti du cadre de la théorie relationnelle, il ne pourra pas répondre à la question et raconte donc n’importe quoi (même si sur le fond, ce qu’il dit à propos de la redondance n’est pas intrinsèquement faux, mais c’est un autre débat). Plus généralement il pratique le sophisme et le ignoratio elenchi pour discréditer à tort et faire accepter d’avance ses propositions (par exemple : "Since SQL is a set oriented language, this is a better model than the usual adjacency list approach you see in most text books)."

    Prudence, donc.

    Le 2e article proposé par Google est le suivant : Managing Hierarchical Data in MySQL. L’auteur réalise un bel exercice technique, mais quand il écrit :
    the management of hierarchical data is not what a relational database is intended for. The tables of a relational database are not hierarchical (like XML), but are simply a flat list. Hierarchical data has a parent-child relationship that is not naturally represented in a relational database table.
    Ou bien il est d’une mauvaise foi patente (décidemment...), ou bien il n’a rien compris à la véritable nature du Modèle Relationnel de Données. Dire qu’une base de données relationnelle est une "flat list", c’est confondre la nature d’une relation (table en SQL) et la représentation graphique, que l’on en fait sur papier sous forme d’un tableau à deux dimensions. Mais l’image d’une chose n’est pas la chose ! Une relation à n attributs est n-dimensionnelle. Par ailleurs, une relation peut servir pour ce que l'on veut — pourquoi pas une hiérarchie — au moyen d’une structure simple (comme celle de la table Hierarchie que je vous ai proposée) et l'on dispose des opérateurs relationnels pour manipuler cette structure. L’auteur ne raisonne manifestement qu’en termes de structure, ce qui est notoirement insuffisant.

    Après cela, Je n'ai pas eu le courage de chercher à accéder aux autres articles proposés par Google...

    Maintenant, si vraiment vos propres tests de performance vous conduisaient à utiliser le "nested set model" ou la technique de la sauvegarde du path, je dirais à la façon de Chevallier et Laspalès : "C’est vous qui voyez"...
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  10. #10
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 8
    Points : 0
    Points
    0
    Par défaut
    Je continue toujours mes recherches/tests, mais j'en profite pour vous faire partager un lien très interessant au sujet du Nested Set Model (modèle intervallaire).

    Sujet global : http://www.dbforums.com/showthread.php?t=400142

    La critique sur le modèle (il semble partager votre point de vue) :http://www.dbforums.com/showpost.php...10&postcount=4

    La réponse de Celko ("l'inventeur du modèle") :
    http://www.dbforums.com/showpost.php...44&postcount=6

    à cela s'ajoute aussi 2 autres critiques / réponses, toujours sur le même sujet.


    Tutorial developpez : http://sqlpro.developpez.com/cours/arborescence/

  11. #11
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    7 945
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 7 945
    Points : 30 716
    Points
    30 716
    Billets dans le blog
    16
    Par défaut Nested Set Model contre Adjacency List Model
    Bonsoir Greg221,


    Citation Envoyé par Greg221 Voir le message
    Je continue toujours mes recherches/tests, mais j'en profite pour vous faire partager un lien très intéressant au sujet du Nested Set Model (modèle intervallaire).

    La critique sur le modèle (il semble partager votre point de vue) : http://www.dbforums.com/showpost.php...10&postcount=4

    La réponse de Celko ("l'inventeur du modèle") :
    http://www.dbforums.com/showpost.php...44&postcount=6
    Je suis d’accord avec l’auteur de la critique, à ceci près que, dès qu’il sort du cadre théorique, disons pour traiter de la performance, il monte trop vite au filet sans assurer ses arrières ce qui se traduit automatiquement par un revers décroisé de la part de celui qui l’attend au tournant.

    Pour sa part, Celko est un renard doublé d'une anguille, et comme je l’ai laissé entendre précédemment, il pratique le sophisme sans complexe (quand je pense qu'il en appelle même à Codd, faussement bien sûr...) Il connaît mieux que quiconque les ficelles SQL et les perdreaux de l’année ne peuvent séparer l’ivraie du bon grain dans ce qu’il raconte. C’est sans aucun doute un grand champion de SQL, mais il en profite pour jouer du cynisme et de la désinformation, je ne lui accorde aucune confiance ("The adjacency list model is based on graph theory and the relational model is based on sets. Graphs are not sets. There are set-oriented tree models other than the Nested Sets model. So, I do not understand why you want to break the relational model when there is no need to do so" : dans la table qu'il met en cause, tous les attributs correspondent à des propriétés naturelles, dont les noms des d'employés, utilisés pour bâtir la hiérarchie, tandis que les bornes qu'il utilise ne sont que des propriétés artificielles, ressemblant plutôt à des pointeurs symboliques, c'est le monde à l'envers, en plus d'être hors sujet, Celko tend un piège...)

    Concernant son modèle, le "Nested Set Model" (abrégeons en NSM), celui-ci permet de faire l’économie de la jointure récursive, lors de la recherche des ascendants ou des descendants concernant un nœud donné, ce qui est un atout certain quand le SGBD dont on se sert ne propose pas ce type de jointure. Mais par exemple avec DB2, Oracle ou SQL Server, je ne vois pas l’intérêt et m’en tiens à la structure hiérarchique que je vous ai proposée, consistant à établir — via la table Hierarchie — des liens entre les attributs TableId de la table MaTable. Essayons d’étayer un peu tout cela. Par opposition au NSM, j’utiliserai l’abréviation ALM pour ce que Celko appelle le "Adjacency List Model" et que je suis supposé utiliser.

    Concernant les SELECT :

    Comme je viens de le dire, la méthode NSM est séduisante, on effectue des requêtes de façon simple, les exemples fournis par Celko et autres le montrent.
    La méthode ALM est simple elle aussi d’emploi, grâce à l’utilisation des vues temporaires d’union récursive que je vous ai proposées (Vue ou MaVue). La recherche d’une descendance est effectuée de façon simple (même chose pour la recherche d’une ascendance), voyez les requêtes que j'ai utilisées.

    Concernant les INSERT :

    Avec la table Hierarchie que je vous ai proposée, insérer un lien de dépendance entre deux éléments de clés respectives i1 et i2 est très simple et ne consomme rien :
    INSERT INTO Hierarchie (TableId, ParentId) VALUES (i1, i2)
    Avec NSM, les choses se gâtent sérieusement, car si la partie codage reste simple (deux UPDATE et un INSERT), disons qu’en moyenne on manipule la moitié des lignes de la table (il faut en effet incrémenter de deux unités toutes les bornes de valeur > i2), donc en moyenne la moitié des pages physiques sont mises à jour (READ/REWRITE), qu’elles soient ou non bufferisées, ce qui est particulièrement néfaste pour la performance et dévastateur quant à la consommation des ressources (CPU, I/O) dès que les volumes traités sont conséquents. Quoi qu’en dise Celko avec ses pages à 16 K (tout en omettant au passage l’aspect CPU), concernant la table de 500000 lignes que j’ai évoquée les jours précédents, je n’ose imaginer les conséquences d’un bon paquet d’ajouts (ou plutôt, je m’empresserai de monter un prototypage de performance avant de m’embarquer pour une aventure à l’issue incertaine...)

    Concernant les DELETE :

    Avec la table Hierarchie que je vous ai proposée, supprimer un lien de dépendance entre deux éléments de clés respectives i1 et i2 reste simple. La consommation de ressources reste faible, sauf bien sûr si l’on supprime le PDG de l’entreprise et que cette suppression doit entraîner celle de l’ensemble de ses collaborateurs.
    Si la suppression d’un nœud entraîne celle de sa descendance, le fait de coder :
    DELETE FROM Hierarchie Where ParentId = i2
    ne suffit pas, car si les enfants de i2 disparaissent de la hiérarchie, les petits-enfants restent présents. Une fois de plus, on utilise donc la jointure récursive pour supprimer la descendance complète :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    WITH Vue (Descendante, Ascendante) AS 
        (
         SELECT TableId, ParentId 
         FROM   Hierarchie  
         WHERE  ParentId = y  
        UNION ALL 
         SELECT I.TableId, I.ParentId  
         FROM   Vue, Hierarchie AS I 
         WHERE  I.ParentId = Vue.Descendante 
        )
     
      Delete from Hierarchie  
             where Exists (Select *
                           From   Vue
                           Where  Vue.Descendante = Hierarchie.TableId) ;
    La même opération reste simple à coder avec NSM, mais comme dans le cas des inserts, la consommation de ressources peut être inacceptable, pour les mêmes raisons.

    Concernant les UPDATE :

    Mêmes causes, mêmes effets. Il s’agit encore d’une variation sur le thème de l’effet d’accordéon consécutif à un changement de valeurs des bornes, aussi je vous laisse le soin d’interpréter ma pensée...

    En conclusion

    La méthode NSM est intéressante pour effectuer des consultations, mais ça s’arrête là. Un prototypage des performances digne de ce nom montrera vraisemblablement que, pour une table de bonne volumétrie, modifier une valeur de borne coûte la feau des pesses (quant à 10, 100, 1000 valeurs...) Enfin, j'espère me tromper, mais j'en ai monté des prototypes...

    Et puis dans tout cela, il faut la construire cette hiérarchie, elle ne tombe pas du ciel. Le calcul de bornes met en jeu un algorithme simple, mais si construire à la main, avec une centaine de lignes c’est jouable, avec 500000 lignes l’affaire se corse singulièrement, c’est l’usine à gaz, il faudra vraisemblablement alors en passer par une table montée selon ce que Celko appelle avec condescendance le fameux Adjacency List Model, avant de remplir la table définie selon le Nested Set Model.

    N'ayant pas prototypé cette affaire, je risque à mon tour un revers décroisé, mais je vous aurai quand même fait part de quelques points de réflexion. Si de votre côté vous avez d'autres éléments...
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  12. #12
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 3
    Points : 3
    Points
    3
    Par défaut pas compatible avec MYSQL
    Trés belle discussion ...

    Mais ta solution n'est pas compatible avec MYSQL.
    Comment peut répondre avec MYSQL

    merci

    PS : je travaille avec Greg sur le meme projet

  13. #13
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    7 945
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 7 945
    Points : 30 716
    Points
    30 716
    Billets dans le blog
    16
    Par défaut
    Bonsoir,


    Citation Envoyé par mbmailing-dev Voir le message
    ta solution n'est pas compatible avec MYSQL.
    Comment peut répondre avec MYSQL
    Ce que j'ai écrit est conforme à la norme SQL.

    Je ne suis pas du tout spécialiste de MYSQL, aussi puis-je déjà vous demander où ça coince ?
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  14. #14
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 8
    Points : 0
    Points
    0
    Par défaut
    Citation Envoyé par fsmrel Voir le message
    Bonsoir,




    Ce que j'ai écrit est conforme à la norme SQL.

    Je ne suis pas du tout spécialiste de MYSQL, aussi puis-je déjà vous demander où ça coince ?

    Il me semble que c'est le mot clé "WITH" qui n'est pas compatible avec MySQL.
    Si j'ai bien compris, c'est une sorte de "CREATE RECURSIVE VIEW" ?

    Je crois qu'il n'y a pas d'équivalent MySQL pour cette fonctionnalité... (je cherche)

  15. #15
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    7 945
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 7 945
    Points : 30 716
    Points
    30 716
    Billets dans le blog
    16
    Par défaut
    Citation Envoyé par Greg221 Voir le message

    Il me semble que c'est le mot clé "WITH" qui n'est pas compatible avec MySQL.
    Si j'ai bien compris, c'est une sorte de "CREATE RECURSIVE VIEW" ?
    (je cherche)
    On est en plein SQL récursif. La clause WITH a été introduite vers 1995 ou 1996 dans IBM DB2 UDB et a la forme générale suivante :


    Ce mécanisme a été repris par la norme SQL et par certains SGBD tels que MS SQL Server (avec lequel j'effectue les tests). Proposez ceci à votre moteur de recherche "with common_table_expression", et vous accéderez à la description de la façon dont on traite de la récursivité avec ce SGBD.

    Vous en aurez l'équivalent DB2 en proposant au moteur de recherche "Examples of recursive common table expressions" :
    http://publib.boulder.ibm.com/infoce...cursivecte.htm

    Comme je l'ai écrit dans un précédent message, Oracle traite de façon différente de la récursivité.

    Si MYSQL ne traite pas de la récursivité, j'ai bien peur qu'il ne vous reste plus qu'à programmer cette partie au sein d'une procédure, ou bien, si vous avez peu de mises à jour, essayez le nested set model...
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  16. #16
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 8
    Points : 0
    Points
    0
    Par défaut
    Citation Envoyé par fsmrel Voir le message
    Si MYSQL ne traite pas de la récursivité, j'ai bien peur qu'il ne vous reste plus qu'à programmer cette partie au sein d'une procédure, ou bien, si vous avez peu de mises à jour, essayez le nested set model...
    J'ai trouvé un document qui traite du problème d'arborescence en base de données (MySQL) avec des procédures récursives (paragraphe 7) : http://www.artfulsoftware.com/mysqlb...qled1ch20.html

    J'ai bien peur que ce soit l'unique solution...

    Quant au nested set model, une amélioration (au niveau des maj) serait de prévoir les bornes (gauche_min, droite_max) lors de chaque insertion de noeud... ce qui éviterait de faire un update de toute la table...

  17. #17
    Membre du Club
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Mars 2002
    Messages
    54
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mars 2002
    Messages : 54
    Points : 58
    Points
    58
    Par défaut
    Bonjour,

    Comme vous, je me pose la question des arborescences. C'est pourquoi je rebondis sur cette discussion de haute voltige.

    Je ne suis pas expert comme vous l'êtes, mais la dernière remarque de fsmrel me parait pertinente. Si le gros inconvénient de NSM pour les INSERT et DELETE est le volume des données mises à jour, pourquoi ne pas réserver des plages de bornes plus larges ? Ainsi, l'insertion d'un enfant ne nécessiterait pas le recalcul des bornes de son parent ni des frères de son parent, etc.

    Est-ce complètement idiot ?

    Cordialement

  18. #18
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 716
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 716
    Points : 52 380
    Points
    52 380
    Billets dans le blog
    4
    Par défaut
    Commencez par tester le modèle d'arborescence à l'aide d'intervalle en nombre entiers. L'UPDATE sur des entiers dans une table, même importante n'est pas toujours quelque chose de très lent. Cela dépend du volume des données. Vous pouvez aussi externalisé l'intervalle en utilisant une table parente en héritage. Si vous voulez une amélioration, vous pouvez utiliser des bornes DECIMAL et donc insérer entre deux bornes sans toucher aux autres.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

Discussions similaires

  1. Structures, padding, optimisations
    Par oodini dans le forum C++
    Réponses: 5
    Dernier message: 08/03/2013, 12h54
  2. structure identique optimisation différente
    Par overider dans le forum Requêtes
    Réponses: 0
    Dernier message: 16/03/2011, 12h33
  3. Desactiver une structure d'optimisation
    Par msami dans le forum Outils
    Réponses: 6
    Dernier message: 23/04/2008, 21h18
  4. Structure FIFO optimisée à l'accès
    Par guipom dans le forum Langage SQL
    Réponses: 5
    Dernier message: 03/11/2005, 10h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo