Mes impressions sur le web, les standards et autres…


SQL et structure arborescente

Dans le cadre d’un projet que je développe en ce moment, j’ai besoin de stocker un arbre dans une base de données, c’est à dire un groupe d’éléments reliés par une relation de type parent-enfant. Plusieurs solutions existent :

Les listes adjacentes

C’est la méthode la plus naturelle et celle à laquelle j’ai d’abord penser. Le principe est tout simplement d’associer à chaque nœud l’identifiant du nœud parent. On peut ensuite extraire nos données de différentes façons avec des auto-jointures (voir le lien vers mysql en fin de billet).

Le problème est que cela n’est pas applicable si la profondeur de l’arbre n’est pas fixée. Il faut alors en passer par une routine récursive (en PHP dans mon cas) pour construire l’arbre et travailler dessus. C’est bourrin, c’est coûteux…

Les ensembles imbriquées ou représentation intervallaire

Moins facile à appréhender, cette technique offre en revanche une bien plus grande facilité pour lire tout ou partie de l’arbre. La plupart des opérations de lecture ne nécessitent qu’une requête SQL !

Le principe est d’assigner à chaque élément deux bornes, les descendants de cet élément étant englobés dans l’interval créé par ces deux bornes. Je me permets de copier ici la représentation visuelle en tranche donnée dans l’article de SQLpro, ça permet de tout de suite se faire une bonne idée du mécanisme :

Représentation sous forme de tranches englobantes du mécanisme des ensembles imbriqués

Je ne m’attarde pas sur les requêtes SQL à utiliser pour consulter un tel arbre, consultez l’excellent article Gestion d'arbres par représentation intervallaire pour en savoir plus.

Ici, donc, pas besoin de récursivité, la lecture est simple et claire. Mais les choses se gâtent dès qu’on souhaite effectuer des changements sur notre arbre. Souhaite t-on ajouter un élément dans notre arbre ? Paf, trois requêtes ! Une pour décaler les bornes droite, une autre pour décaler les bornes gauches, et enfin, la requête pour insérer le nouvel élément. Et si plusieurs modifications peuvent potentiellement survenir quasiment au même moment, ne pas utiliser les transactions, et donc, dans le cas de MySQL, les tables innoDB, serait plutôt hasardeux.

Autres idées

Comme autre technique, il y en a une qui consiste à stocker carrément le chemin canonisé d’un élément à la racine. Pas super élégant et viable seulement pour des petits arbrisseaux ;¬)

J’ai vaguement pensé à stocker la structure de l’arbre sous forme XML, elle-même stockée dans la base de données, mais là comme ça, sans creuser l’idée, je me dis que les performances ne seront pas vraiment au rendez-vous. Qu’en penses-tu toi, visiteur perdu sur mon journal ? Et si tu as d’autres idées pour gérer un arbre, n’hésite pas ;¬)