Bons aperçus
De manière générale, vous décidez entre des temps de lecture rapides (par exemple, un ensemble imbriqué) ou des temps d'écriture rapides (liste d'adjacence). Habituellement, vous vous retrouvez avec une combinaison des options ci-dessous qui correspondent le mieux à vos besoins. Ce qui suit fournit une lecture approfondie:
- Encore une comparaison des intervalles imbriqués et de la liste d'adjacence : la meilleure comparaison que j'ai trouvée de la liste d'adjacence, du chemin matérialisé, de l'ensemble imbriqué et de l'intervalle imbriqué.
- Modèles de données hiérarchiques : diapositives avec de bonnes explications des compromis et des exemples d'utilisation
- Représenter les hiérarchies dans MySQL : très bon aperçu de l'ensemble imbriqué en particulier
- Données hiérarchiques dans les SGBDR : ensemble de liens le plus complet et le mieux organisé que j'ai vu, mais peu d'explications
Les options
Ceux que je connais et les caractéristiques générales:
- Liste d'adjacence :
- Colonnes: ID, ParentID
- Facile à mettre en œuvre.
- Déplacements, insertions et suppressions de nœuds bon marché.
- Cher pour trouver le niveau, l'ascendance et les descendants, le chemin
- Évitez N + 1 via les expressions de table communes dans les bases de données qui les prennent en charge
- Ensemble imbriqué (aka Traversée d'arbre de précommande modifiée )
- Colonnes: gauche, droite
- Ascendance bon marché, descendants
O(n/2)
Déplacements, insertions et suppressions très coûteux en raison d'un encodage volatil
- Bridge Bridge (aka Closure Table / w triggers )
- Utilise une table de jointure séparée avec: ancêtre, descendant, profondeur (facultatif)
- Ascendance et descendants bon marché
- Écrit les coûts
O(log n)
(taille de la sous-arborescence) pour l'insertion, les mises à jour et les suppressions - Encodage normalisé: bon pour les statistiques RDBMS et le planificateur de requêtes dans les jointures
- Nécessite plusieurs lignes par nœud
- Colonne de lignage (alias chemin matérialisé , énumération des chemins)
- Colonne: lignée (par exemple / parent / enfant / petit-enfant / etc ...)
- Descendants bon marché via une requête de préfixe (par exemple
LEFT(lineage, #) = '/enumerated/path'
) - Écrit les coûts
O(log n)
(taille de la sous-arborescence) pour l'insertion, les mises à jour et les suppressions - Non relationnel: repose sur le type de données du tableau ou le format de chaîne sérialisé
- Intervalles imbriqués
- Comme un ensemble imbriqué, mais avec un réel / flottant / décimal pour que l'encodage ne soit pas volatile (déplacement / insertion / suppression peu coûteux)
- A des problèmes de représentation / précision réelle / flottante / décimale
- La variante d'encodage matriciel ajoute l'encodage ancêtre (chemin matérialisé) pour "gratuit", mais avec une astuce supplémentaire d'algèbre linéaire.
- Table plate
- Une liste d'adjacence modifiée qui ajoute une colonne de niveau et de rang (par exemple la commande) à chaque enregistrement.
- Pas cher pour itérer / paginer sur
- Déplacement et suppression coûteux
- Bon usage: discussion filetée - forums / commentaires de blog
- Plusieurs colonnes de lignée
- Colonnes: une pour chaque niveau de lignée, fait référence à tous les parents jusqu'à la racine, les niveaux inférieurs au niveau de l'élément sont définis sur NULL
- Ancêtres, descendants, niveau bon marché
- Insertion bon marché, suppression, déplacement des feuilles
- Insertion, suppression, déplacement coûteux des nœuds internes
- Limite stricte de la profondeur de la hiérarchie
Notes spécifiques à la base de données
MySQL
Oracle
- Utilisez CONNECT BY pour parcourir les listes d'adjacence
PostgreSQL
- Type de données ltree pour le chemin matérialisé
serveur SQL
- Résumé général
- 2008 propose que le type de données HierarchyId semble aider l'approche de la colonne de lignage et étendre la profondeur qui peut être représentée.
Closure Tables
sont supérieurs àAdjacency List
,Path Enumeration
etNested Sets
en termes de facilité d'utilisation (et je devine la performance aussi bien).