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

Langage SQL Discussion :

Gestion d'arbres par représentation intervallaire


Sujet :

Langage SQL

  1. #1
    Membre à l'essai
    Inscrit en
    Septembre 2007
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 29
    Points : 17
    Points
    17
    Par défaut Gestion d'arbres par représentation intervallaire
    Dans le même thème: je me demande si recalculer toute une structure (càd rafraichir toutes les bornes) serait lourd ou non.

    La solution d'arbres par représentation intervallaire me séduit mais dans mon cas, la structure existe déjà (StructId, ParentId).
    Je n ai pas de grands arbres (+- 5 niveaux).

    Je me mets a essayer rapidement d'écrire une procédure qui me fixerait les bornes. Si ce n'est pas trop lourd, je compte me passer de toute une gestion "immédiate" (update/insert/delete) pour ne garder qu'une "grosse" procédure de rafraichissement.

    ...edit:
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
     
    BEGIN TRAN
    --Declare
    DECLARE @Counter                INTEGER
    DECLARE @LoopMax                INTEGER
    DECLARE @ActualParentId    BIGINT
    DECLARE @ActualChildId    BIGINT
     
    DECLARE @ActualTreeL        INTEGER
    DECLARE @ActualTreeR        INTEGER
    DECLARE @ActualLevel        INTEGER
     
    --Init
    SELECT @Counter = COUNT(*) FROM Est_Structure WHERE Est_HeaderId = 1
    SET @ActualParentId = NULL
    SET @ActualChildId = NULL
    SET @ActualLevel = 0
    SET @LoopMax = @Counter
     
    --Reset All
    UPDATE Est_Structure set TreeL=NULL, TreeR=NULL WHERE Est_HeaderId = 1
    --Set root:
    UPDATE Est_Structure SET TreeL = 1, Level = 0, TreeR = @Counter*2
       WHERE Est_HeaderId = 1 AND ParentId IS NULL
     
    SET @Counter = 0
    WHILE EXISTS (SELECT NULL FROM Est_Structure WHERE Est_HeaderId = 1 AND TreeL IS NULL)
        AND @Counter < @LoopMax
    BEGIN
        -- Loop - Begin
        SET @Counter = @Counter + 1
        SELECT TOP 1 @ActualChildId = Child.Est_StructureId, @ActualParentId = Child.ParentId
                , @ActualTreeL = Parent.TreeL
                , @ActualLevel = Parent.[Level]
            FROM Est_Structure Child INNER JOIN Est_Structure Parent ON Parent.Est_StructureId = Child.ParentId
            WHERE Child.Est_HeaderId = 1
                AND Child.TreeL IS NULL
                AND Child.ParentId IS NOT NULL
                AND ( @ActualParentId IS NULL OR (@ActualParentId IS NOT NULL AND @ActualParentId = Child.ParentId))
            ORDER BY Child.[Level], Child.[Type] DESC
     
        --Get next value of TreeL...
        SELECT @ActualTreeL = ISNULL(MAX(TreeL),1) FROM Est_Structure WHERE Est_HeaderId = 1 AND TreeL IS NOT NULL
        SELECT @ActualTreeR = ISNULL(MAX(TreeR),0) FROM Est_Structure WHERE Est_HeaderId = 1 AND TreeR IS NOT NULL AND ParentId IS NOT NULL --AND TreeR < @LoopMax
        SELECT @Error = @@ERROR, @Rowcount = @@ROWCOUNT
        IF @ActualTreeR IS NOT NULL AND @ActualTreeR > @ActualTreeL
        SET @ActualTreeL = @ActualTreeR
     
        IF NOT EXISTS (SELECT NULL FROM Est_Structure WHERE Est_HeaderId = 1 AND ParentId = @ActualChildId)
        BEGIN
            --Feuilles... TreeR = TreeL + 1
            UPDATE Est_Structure SET TreeL = @ActualTreeL+1, TreeR = @ActualTreeL+2
                , [Level] = @ActualLevel+1
                WHERE Est_StructureId = @ActualChildId
            SET @ActualTreeL = @ActualTreeL + 2
        END
        ELSE
        BEGIN
            UPDATE Est_Structure SET TreeL = @ActualTreeL+1
                , [Level] = @ActualLevel+1
                WHERE Est_StructureId = @ActualChildId
            SET @ActualTreeL = @ActualTreeL + 1
     
            IF EXISTS (SELECT NULL FROM Est_Structure WHERE ParentId = @ActualChildId AND TreeL IS NULL)
            BEGIN
                PRINT 'Use ChildId as ActualParentId...'
                UPDATE Est_Structure SET TreeR = @ActualTreeL+1 WHERE TreeR IS NULL AND Est_StructureId = @ActualParentId AND ParentId IS NOT NULL
                IF @@ROWCOUNT > 0 SET @ActualTreeL = @ActualTreeL + 1 
                SET @ActualParentId = @ActualChildId
            END            
        END
     
        WHILE @ActualParentId IS NOT NULL
            AND NOT EXISTS (SELECT NULL FROM Est_Structure WHERE Est_HeaderId = 1 AND TreeL IS NULL AND ParentId = @ActualParentId)
        BEGIN
            UPDATE Est_Structure SET TreeR = @ActualTreeL+1 WHERE TreeR IS NULL AND Est_StructureId = @ActualParentId
            IF @@Rowcount > 0 SET @ActualTreeL = @ActualTreeL + 1 
            SELECT @ActualParentId = ParentId FROM Est_Structure WHERE Est_StructureId = @ActualParentId
        END
        -- Loop - End
    END
     
    --Results:
    SELECT Est_StructureId, ParentId, Level, Rang, TreeL, TreeR, Type, BDE_NR, Bezug, Pos, Artikel
        FROM Est_Structure
        WHERE Est_HeaderId = 1
    --        AND TreeL IS NOT NULL
    --     AND (BDE_NR = 464915 OR BEZUG = 464915)
        ORDER By TreeL, Rang, BDE_NR, Pos, [Level]
     
    ROLLBACK
    63ms pour un arbre sur 4 niveaux composé de 92 rows... ok pour moi
    (...Est_HeaderId est l'identifiant de mon arbre...)

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 774
    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 774
    Points : 52 743
    Points
    52 743
    Billets dans le blog
    5
    Par défaut
    Avez vous fait des tests en concurrence ? Par ce que des test en mono utilisateur dans une base de données c'est inutile !

    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/ * * * * *

  3. #3
    Membre à l'essai
    Inscrit en
    Septembre 2007
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 29
    Points : 17
    Points
    17
    Par défaut
    Non, je n ai pas fait des tests en concurrence.
    Je voulais tout d abord vérifier que ce genre de solution etait concevable.

    Dans mon cas, la concurrence n a pas trop d interet: le concept donne un proprietaire a l arbre. Un autre utilisateur pourrait cependant (dans de rare cas) le parcourir en meme temps, mais pas le modifié.

    Des que j ai vu que ca avait l air de tenir la route, j ai ecrit mon code plus proprement (gestion d erreurs, WITH (NOLOCK),...)

    Je concois bien que ce genre de solution ne peut pas toujours convenir! Je supposais que c etait clair... mais c est vrai qu il vaut mieux prevenir...

    Merci

    Edit:
    Au niveau performance, j ai réessayé avec un plus grand arbre (composé de 1185 rows/ level 7)... il me faut en moyenne +-1200ms... bof bof au niveau performance. Dans mon cas: l arbre ne devrait jamais etre aussi grand (mais bon... la theorie et la pratique...). Ca reste acceptable pour mon projet... ca ne le sera pas dans d autres cas!
    Toute optimisation sera la bienvenue

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 774
    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 774
    Points : 52 743
    Points
    52 743
    Billets dans le blog
    5
    Par défaut
    En matière de BD les temps de réponse sont rarement linéaires. Ils sont généralement exponentiel sans indexation et logarithmique avec les bons index. Et surtout, pour pouvoir réellement apprécier un test il faut un volume minimale de données (généralement supérieur à la RAM du serveur) et plusieurs accès concurrent. Autrement dit avec 100 ou 1000 lignes c'est du pipi de chat !

    L'utilisation de NOLOCK n'y changera rien (c'est une aberration et une preuve que le sujet n'est pas maitrisé en général) car dans les mises à jour, il y a toujours verrouillage des tables.

    Enfin, la mise à jour au fil de l'eau (donc à chaque INSERT/UPDATE/DELETE) dilue les temps de réponse qui deviennent quasi invisible, alors que le batch, même s'il est globalement moins couteux, verrouillera plus longtemps ce qui donnera vu de l'utilisateur des temps de réponse erratique en sus d'exposer des données fausses.

    Bref, votre méthode est totalement inadaptée et montre qu'en matière de développement vous en êtes resté à l'itératif et non à l'ensembliste ni au transactionnel !

    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/ * * * * *

  5. #5
    Membre à l'essai
    Inscrit en
    Septembre 2007
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 29
    Points : 17
    Points
    17
    Par défaut
    Un paramètre a ne pas néglier: le temps consacré à ce projet: très limité (en heures...pas en jours)
    et son utilisation : 4 personnes... quelques fois sur la semaine...(+-5x => appel de +-5x de cette procédure)
    C est juste une question de priorité: le temps que je n utilise pas ici, je l utilise a gagner du temps là ou c est vraiment nécessaire.

    100 ou 1000 lignes c'est du pipi de chat !
    c est clair => d ou l interet de ne pas perdre trop de temps à essayer de gagner du temps.

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 774
    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 774
    Points : 52 743
    Points
    52 743
    Billets dans le blog
    5
    Par défaut
    Vous pouvez parfaitement utiliser les procédures que j'ai mis au point : soit en ajoutant les colonnes à la table, soit en ajoutant une table liée en 1:1 à la table source et en utilisant des déclencheurs pour ce faire.

    Voici les code des PS que j'ai écrit :
    http://blog.developpez.com/sqlpro/p8...allaire-proce/
    http://blog.developpez.com/sqlpro/p7...dure-de-depla/
    http://blog.developpez.com/sqlpro/p7...dure-de-derec/

    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/ * * * * *

  7. #7
    Membre à l'essai
    Inscrit en
    Septembre 2007
    Messages
    29
    Détails du profil
    Informations forums :
    Inscription : Septembre 2007
    Messages : 29
    Points : 17
    Points
    17
    Par défaut

    tip top pour faire ca proprement. J espere trouvé du temps pour le faire. Ensuite ce sera egalement disponible pour d autres futurs projets

Discussions similaires

  1. Gestion d'arbres par représentation intervallaire - Déplacements et tris
    Par samche dans le forum Algorithmes et structures de données
    Réponses: 11
    Dernier message: 18/06/2013, 15h58
  2. Réponses: 0
    Dernier message: 24/08/2007, 10h19
  3. Gestion d'arbres par représentation intervallaire
    Par Djebel dans le forum Langage SQL
    Réponses: 4
    Dernier message: 15/10/2006, 17h28
  4. arbre par représentation intervallaire
    Par peuf23 dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 13/10/2006, 23h16
  5. Gestion d'arbres par représentation intervallaire
    Par brice01 dans le forum Langage SQL
    Réponses: 4
    Dernier message: 23/01/2006, 21h20

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