Quelles sont les options pour le stockage de données hiérarchiques dans une base de données relationnelle?
Bonne Aperçus
Généralement parlant, vous êtes prise d'une décision rapide entre les temps de lecture (par exemple, l'ensemble imbriqué) ou rapide le temps d'écriture (liste d'adjacence). Habituellement, vous vous retrouvez avec une combinaison des options ci-dessous qui correspondent le mieux à vos besoins. Voici quelques une lecture approfondie:
- Un Imbriqués Intervalles vs la Contiguïté de la Liste de comparaison: la meilleure comparaison de Liste d'Adjacence, Chemin Matérialisé, Ensemble Imbriqué et Imbriquées Intervalle, j'ai trouvé.
- Les modèles de données hiérarchiques: les lames avec de bonnes explications de compromis et exemple d'utilisation
- Représentant des hiérarchies dans MySQL: très bon aperçu de l'Ensemble Imbriqué en particulier
- Des données hiérarchiques dans des Sgbdr: le plus complet et bien organisé ensemble de liens que j'ai vu, mais pas beaucoup dans la voie de l'explication
Options
Ceux que je suis au courant et caractéristiques générales:
- Liste D'Adjacence:
- Colonnes: ID, ParentID
- Facile à mettre en œuvre.
- Pas cher nœud se déplace, des insertions et des suppressions.
- Cher pour trouver le niveau, l'ascendance & descendants, chemin
- Éviter de N+1 par l'intermédiaire d' Les Expressions De Table Communes dans les bases de données qui prennent en charge eux
- Ensemble Imbriqué (un.k.un Modifié En Précommande Arbre Transversal)
- Colonnes: À Gauche, À Droite
- Pas cher de l'ascendance, de descendance
- Très cher
O(n/2)
se déplace, les insertions, les suppressions du fait de la volatilité de l'encodage
- Table De Bridge (un.k.un. Fermeture de la Table /w déclencheurs)
- Utilise la table de jointure séparée avec: ancêtre, descendant, de la profondeur (en option)
- Pas cher l'ascendance et de la descendance
- Écrit coûts
O(log n)
(taille du sous-arbre) pour l'insertion, mises à jour, suppressions - Normalisé d'encodage: bon pour le SGBDR statistiques & planificateur de requête dans les jointures
- Nécessite plusieurs lignes par nœud
- La Lignée De La Colonne (un.k.un. Chemin Matérialisé, Chemin De L'Énumération)
- Colonne: la lignée (par exemple, /parent/enfant/petit enfant/etc...)
- Pas cher descendants via le préfixe de la requête (par exemple,
LEFT(lineage, #) = '/enumerated/path'
) - Écrit coûts
O(log n)
(taille du sous-arbre) pour l'insertion, mises à jour, suppressions - Non-relationnelles: s'appuie sur le Tableau de type de données ou chaîne sérialisée format
- Imbriqués Les Intervalles De
- Comme ensemble imbriqué, mais avec de vrais/float/décimal de sorte que l'encodage n'est pas volatile (peu coûteux de déplacer/insérer/supprimer)
- A vrai/float/représentation décimale/précision questions
- Matrice de variantes de codage ajoute ancêtre de l'encodage (chemin matérialisé) pour le "libre", mais avec une trickiness de l'algèbre linéaire.
- Table À Plat
- Une modification de la Liste d'Adjacence, qui ajoute un Niveau et le Rang (par exemple, la commande) colonne pour chaque enregistrement.
- Pas cher pour itérer/paginer sur
- Cher déplacer et de supprimer des
- Bon Usage: fils de discussion - forum /blog de commentaires
- Plusieurs colonnes de lignage
- Colonnes: une pour chaque lignée niveau, se réfère à tous les parents jusqu'à la racine, niveaux plus bas que le niveau de l'objet sont mis à NULL
- Pas cher ascendants, descendants, niveau
- Bon marché insérer, supprimer, déplacer des feuilles
- Cher, insérer, supprimer, déplacer des nœuds internes
- Dur de limite à la profondeur de la hiérarchie peut être
De La Base De Données Des Notes Spécifiques
MySQL
Oracle
- Utilisation SE CONNECTER PAR de parcourir les Listes d'Adjacence
PostgreSQL
- ltree type de données de Chemin Matérialisé
SQL Server
- Résumé général
- 2008 offre HierarchyId type de données apparaît pour vous aider avec la Lignée de la Colonne d'approche et d'étendre la profondeur qui peut être représenté.
- Selon slideshare.net/billkarwin/sql-antipatterns-strike-back de la page 77,
Closure Tables
sont supérieures àAdjacency List
,Path Enumeration
etNested Sets
en termes de facilité d'utilisation (et je devine aussi bien de la performance). - Je m'ennuie très simple version ici: une simple GOUTTE. Si votre hiérarchie a seulement quelques dozend éléments sérialisé arbre de id pourrait être la meilleure option.
- la question est un wiki de la communauté, alors n'hésitez pas à avoir à elle. Ma pensée à cet égard, je tiens seulement à faire avec ces bases de données qui prennent en charge une sorte de blob structurants tels que XML stables avec un langage de requête comme XPATH. Sinon, je ne vois pas une bonne façon d'interrogation à côté de récupération, de désérialiser, et munge dans le code, pas SQL. Et si vous avez vraiment un problème où vous avez besoin d'un grand nombre de l'arbitraire des éléments, vous pourriez être mieux de l'aide d'un Noeud de base de données comme Neo4J, que j'ai utilisé et aimé, mais jamais pris jusqu'à la production.
- Pour MS SQL Server: Combinaison de l'Id-ParentId et HierarchyId Approches Hiérarchiques de Données
- Que MSDN lien "Synthèse Générale" n'affiche plus l'article. C'était en septembre 2008, édition de MSDN Magazine, que vous pouvez télécharger en tant que fichier CHM, ou à voir via le web archive: web.archive.org/web/20080913041559/http://msdn.microsoft.com:80/...
Vous devez vous connecter pour publier un commentaire.
Mon préféré réponse est que ce que la première phrase de ce fil suggéré. Utiliser une Liste d'Adjacence pour maintenir la hiérarchie et de l'utilisation Imbriquée Définit à la requête de la hiérarchie.
Le problème jusqu'à maintenant a été que la coversion méthode à partir d'un Adjacecy Liste Imbriquée Ensembles a été horriblement lent, car la plupart des gens utilisent l'extrême RBAR méthode connue sous le nom de "Pousser la Pile des" à faire la conversion et a été considéré comme un moyen de coûteux d'atteindre le Nirvana de la simplicité de maintenance de la Liste d'Adjacence et la performance impressionnante de Imbriquée Ensembles. En conséquence, la plupart des gens finissent par avoir à trancher pour l'un ou l'autre, surtout si il ya plus de, disons, un moche de 100 000 nœuds ou plus. L'utilisation de la commande de la pile méthode peut prendre une journée entière pour faire la conversion sur ce MLM ils considèrent comme un petit million de nœud de hiérarchie.
J'ai pensé donner Celko un peu de la concurrence et à venir avec une méthode pour convertir une Liste d'Adjacence Imbriquées jeux à des vitesses qui semblent tout simplement impossible. Voici la performance de la pile push méthode sur mon i5 ordinateur portable.
Et voici la durée de la nouvelle méthode (avec la poussée de la pile de la méthode dans la parenthèse).
Oui, c'est correct. 1 million de nœuds convertis en moins d'une minute et 100 000 nœuds en moins de 4 secondes.
Vous pouvez lire au sujet de la nouvelle méthode et d'obtenir une copie du code à l'adresse suivante.
http://www.sqlservercentral.com/articles/Hierarchy/94040/
J'ai également développé un "pré-agrégées" hiérarchie à l'aide de méthodes similaires. MLM croyants et les gens qui font des listes de matériaux seront particulièrement intéressés par le présent article.
http://www.sqlservercentral.com/articles/T-SQL/94570/
Si vous ne s'arrêter pour jeter un oeil à l'article, sauter dans le "Join the discussion" et laissez-moi savoir ce que vous en pensez.
C'est un très répondre en partie à votre question, mais j'espère toujours utile.
Microsoft SQL Server 2008 met en œuvre deux caractéristiques qui sont extrêmement utiles pour la gestion des données hiérarchiques:
Ont un coup d'oeil à "Le modèle de Votre hiérarchie des Données Avec SQL Server 2008" par Kent Tegels sur MSDN pour les mises en chantier. Voir aussi à ma propre question: Récursive même requête création de table dans SQL Server 2008
Cette conception n'était pas encore mentionné:
Plusieurs colonnes de lignage
Si elle a des limites, si vous pouvez supporter, c'est très simple et très efficace. Caractéristiques:
Voici un exemple - arbre taxonomique des oiseaux de la hiérarchie est donc de Classe/Ordre/Famille/Genre/Espèce espèce est le niveau le plus bas, 1 ligne = 1 taxon (ce qui correspond à des espèces dans le cas de nœuds feuilles):
et de l'exemple de données:
Ce qui est excellent, car de cette façon vous accomplir toutes les opérations d'une manière très facile, aussi longtemps que les catégories ne change pas de niveau dans l'arborescence.
D'Adjacence Modèle + Imbriquée Définit Le Modèle
Je suis pour parce que je pouvais insérer de nouveaux éléments à l'arbre facilement (vous avez juste besoin d'une branche de l'id pour insérer un nouvel élément à elle), et aussi de la requête assez vite.
parent
colonne.lft
entrelft
etrgt
de parent.lft
inférieure du nœudlft
etrgt
plus grand que le nœud durgt
et triez les parparent
.J'avais besoin de rendre l'accès et l'interrogation de l'arbre plus vite que les inserts, c'est pourquoi j'ai choisi ce
Le seul problème est de fixer le
left
etright
colonnes lors de l'insertion de nouveaux éléments. eh bien, j'ai créé une procédure stockée pour elle et l'a appelé à chaque fois que j'ai inséré un nouveau point qui est rare dans mon cas, mais il est vraiment très rapide.J'ai eu l'idée de le Joe Celko du livre et de la procédure stockée et comment je suis venu avec elle, c'est expliqué ici en DBA SE
https://dba.stackexchange.com/q/89051/41481
children
etdescendants
.left
etright
sont utilisés pour trouver les descendants.Si votre base de données prend en charge les tableaux, vous pouvez également mettre en place une lignée de colonne ou de chemin matérialisé comme un tableau de parent id.
Spécifiquement avec Postgres vous pouvez ensuite utiliser l'ensemble des opérateurs de requête de la hiérarchie, et d'obtenir d'excellentes performances avec GIN indices. Cela rend la recherche de parents, d'enfants, et de la profondeur assez trivial dans une seule requête. Les mises à jour sont assez gérable ainsi.
J'ai une écriture complète de l'aide des tableaux pour matérialisée chemins si vous êtes curieux.
C'est vraiment une cheville carrée, ronde trou question.
Si les bases de données relationnelles et SQL sont les seuls marteau vous avez ou êtes prêt à utiliser, les réponses qui ont été publiés à ce jour sont suffisantes. Cependant, pourquoi ne pas utiliser un outil conçu pour gérer des données hiérarchiques? Graphique de la base de données sont idéales pour les complexes de données hiérarchiques.
L'inefficacité du modèle relationnel avec les complexités de tout code/requête solution à la carte, un graphique/modèle hiérarchique sur un modèle relationnel est tout simplement pas en vaut la peine lorsque comparé à la facilité avec laquelle un graphe solution de base de données permet de résoudre le problème.
Examiner un projet de Loi de Matériaux comme le commun des données hiérarchiques de la structure.
Plus court chemin entre deux sous-ensembles: graphique Simple traversée de l'algorithme. Acceptable chemins peuvent être qualifiés en fonction des critères.
Similitude: Quel est le degré de similitude entre les deux assemblées? Effectuer un parcours sur les deux sous-arbres de calcul de l'intersection et l'union de deux sous-arbres. Le pourcentage similaire est à l'intersection divisé par l'union.
Fermeture Transitive: Marcher dans les sous-arbre et de résumer le domaine(s) d'intérêt, par exemple, "Combien d'aluminium est à un sous-ensemble?"
Oui, vous pouvez résoudre le problème avec SQL et une base de données relationnelle. Cependant, il ya beaucoup d'approches mieux si vous êtes prêt à utiliser le bon outil pour le travail.
Je suis en utilisant PostgreSQL avec la fermeture des tables pour mon hiérarchies.
J'ai un universel de la procédure stockée pour l'ensemble de la base de données:
Ensuite, pour chaque table, où j'ai une hiérarchie, j'ai créer un déclencheur
Pour le remplissage d'une fermeture de la table de hiérarchie existante-je utiliser cette procédure stockée:
Fermeture tables sont définies avec 3 colonnes - ANCESTOR_ID, DESCENDANT_ID, de la PROFONDEUR. Il est possible (et j'ai même des conseils) pour stocker des enregistrements avec la même valeur pour ANCÊTRE et DESCENDANT, et une valeur de zéro pour la PROFONDEUR. Ceci permettra de simplifier les requêtes pour la récupération de la hiérarchie. Et ils sont en réalité très simple: