Question

Ceci est un Suivi:
MySQL - Est-il possible d'obtenir toutes sous-éléments dans une hiérarchie

J'ai une profondeur d'arbitraire contiguïté modèle de liste Table (je suis au point que je peut convertir en un modèle de jeu imbriqué .

Je lis les données de MySQL sur la façon d'utiliser un modèle de jeu imbriqué, mais il semblait se de plus en plus complexe et très complexe à faire les fonctions de base telles que l'insertion, la mise à jour et la suppression.

Un autre blog montrant comment utiliser un système de déclenchement avec le modèle de liste de contiguïté de garder une table des ancêtres qui se rapporte chaque objet à ses ancêtres.


En ce moment, je dois être en mesure de retourner une liste de tous les enfants d'un noeud donné, de modifier ou de les supprimer. Cette structure hiérarchique ne changera pas tout le temps une fois créé, mais il y aura une quantité de masse des structures hiérarchiques.

Les trois méthodes que je vois sont:

  1. Création d'une procédure stockée qui ferait une requête récursive qui renvoie tous les enfants.

  2. Convertir Nested Set modèle qui nécessiterait d'entrer dans la complexité et peut-être créer une procédure stockée pour ajouter, modifier et supprimer dans cela.

  3. Créer l'Ancêtre Tableau décrits ci-dessus à l'insertion / suppression des déclencheurs pour gérer toutes les données.

S'il y a d'autres méthodes que je ne suis pas explorer, s'il vous plaît laissez-moi savoir et je vais mettre à jour cette liste.

Était-ce utile?

La solution

Quassnoi a exécuter des tests de performance sur le modèle des ensembles imbriqués et le modèle de liste de contiguïté et documenté les résultats et recommandations son blog liste contiguïté vs ensembles imbriqués: MySQL . Le résumé est:

  • jeux est plus rapide pour emboîtées aller chercher tous les nœuds enfants ou tous les nœuds parents.
  • ensembles emboîtés est une mauvaise idée si vous avez souvent besoin de mettre à jour le tableau.

Voici la conclusion de son article:

  

Dans MySQL, le modèle des ensembles imbriqués doit être préférée si les mises à jour de la structure hierarhical sont rares et il est abordable pour verrouiller la table pendant toute la durée d'une mise à jour (qui peut prendre plusieurs minutes sur une longue table).

     

Cela implique la création de la table en utilisant le moteur de stockage MyISAM, créant le cadre de sélection d'un type de géométrie telle que décrite ci-dessus, l'indexation avec un index spatial et persistant au niveau de la table.

     

Si les mises à jour de la table sont fréquents ou il est inaffordable de verrouiller la table pendant une longue période de temps implicite par une mise à jour, le modèle de liste de contiguïté doit être utilisée pour stocker les données hiérarchiques.

     

Cela nécessite la création d'une fonction pour interroger la table.

Le reste de l'article montre comment définir la table, mettre en œuvre les requêtes et donne des mesures de performance. L'utilisation de l'index spatial est une idée intelligente pour améliorer les performances du modèle de jeu imbriqué qui pourrait être nouveau pour vous.


Si vous aussi envisager des approches sans MySQL, vous voudrez peut-être regarder PostgreSQL qui est un autre libre et base de données open source. PostgreSQL supporte les requêtes récursives sous forme de récursive expressions de table commune ce qui rend la recherche de données heirarchical plus facile que dans MySQL et aussi donner de meilleures performances. Quassnoi a également écrit un article contiguïté liste imbriquée vs. jeux: PostgreSQL qui montre les détails

.

Alors que nous parlons de la recherche à d'autres approches, la base de données Oracle est également intéressant de mentionner un. Oracle ont également une extension personnalisée CONNECT BY qui rend la recherche de données heirarchical très facile et rapide. article Quassnoi Liste contiguïté par rapport à des ensembles imbriqués: Oracle nouveau couvre les détails de performance. La requête dont vous avez besoin pour obtenir tous les enfants est extrêmement simple dans ce cas:

SELECT *
FROM yourtable
START WITH id = 42
CONNECT BY parent = PRIOR id

Autres conseils

Je serais toujours aller avec le Nested Set pour la simplicité de cisaillement et convienience. Je suggère toujours cet article . Il montre les requêtes excelent qui sont nécessaires pour le travail avec ces données hierachrchical. Le seul inconvénient que je vois ici est qu'il peut devenir plus lent avec l'insertion / updateing nouveaux enregistrements lorsque le hierachry a atteint un certain niveau de complexité, mais la lecture est plus rapide que beaucoup d'autres solutions que je hae vu.

Pour vous donner un exemple de l'article ci-dessus:

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name = 'ELECTRONICS';

+-------------+----------------------+--------------+-------+
| lev1        | lev2                 | lev3         | lev4  |
+-------------+----------------------+--------------+-------+
| ELECTRONICS | TELEVISIONS          | TUBE         | NULL  |
| ELECTRONICS | TELEVISIONS          | LCD          | NULL  |
| ELECTRONICS | TELEVISIONS          | PLASMA       | NULL  |
| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS  | FLASH |
| ELECTRONICS | PORTABLE ELECTRONICS | CD PLAYERS   | NULL  |
| ELECTRONICS | PORTABLE ELECTRONICS | 2 WAY RADIOS | NULL  |
+-------------+----------------------+--------------+-------+
6 rows in set (0.00 sec)

SQL sage, je ne pense pas qu'il peut obtenir une plus jolie et plus simple;)

Je n'ai aucune idée à procédure stockée chemin. Mais comme il involces récursion (dans votre cas), je ne sais pas si ce sera rapide avec de nombreux niveaux dans la hiérarchie. Je suppose que vous pouvez essayer.

Peut-être que vous devriez envisager d'utiliser la base de données orientée document comme MongoDB . Il pourrait vous rendre la vie beaucoup plus facile.

Lorsque vous traitez avec des ensembles de données hiérarchiques je trouve qu'il vaut mieux aborder avec la mise en cache à l'esprit. L'un des principaux avantages de cette façon de traiter cette question de cette façon est qu'il ne nécessite pas que vous dénormaliser base de données en quelque chose qui pourrait être plus difficile à muter.

Depuis des tas de mémoire (de memcache lookups, Redis, etc) sont beaucoup plus rapides que SQL pour les résolutions simples id -> data, je les utilise pour mettre en cache une liste des ids des enfants directs pour chaque nœud. De cette façon, vous pouvez obtenir des performances décentes via un algorithme récursif pour construire une liste complète pour un nœud.

Pour ajouter / supprimer un nouveau nœud, vous aurez seulement besoin d'invalider son O(1) cache parent direct.

Si ce n'est pas assez vite, vous pouvez ajouter une autre couche de cache à une liste de tous les enfants d'un noeud à chaque noeud. Pour que cela fonctionne avec un jeu de données décemment mutable, vous devez enregistrer les performances du cache (rapport de hits frais / cache) de chaque nœud et définir un niveau de tolérance pour le moment de stocker le cache. Cela peut aussi être stocké dans un segment de mémoire car il est des données non vitales.

Si vous utilisez ce modèle de mise en cache plus avancé, vous aurez besoin de noter ces enfants complets nœud listes devront être invalidée lorsque l'un des enfants de celui-ci sont changés O(log n).

Une fois que vous avez votre liste d'enfants id vous pouvez utiliser est la syntaxe WHERE id IN( id1, id2, .... ) de SQL pour interroger ce que vous voulez.

J'ai eu à stocker un système hiérarchique profondeur d'arbitraire matière de facturation de complexe dans un gestionnaire base de données de type SQL qui n'a pas été vraiment à la tâche, et il a fini par forcer indicies de désordre et délicate, les définitions de données, requêtes, etc. Après avoir redémarré à partir de zéro, en utilisant le gestionnaire de db pour fournir seulement une API pour l'enregistrement lit et écrit sur les clés indexées simples, et faire tout de l'entrée réelle / manipulation / rapports dans le code externe, le résultat final a été plus rapide à mettre en œuvre , plus facile à comprendre et plus simple à maintenir et améliorer. La plus requête complexe nécessaire a été essentiellement SELECT A de B.

Alors, au lieu d'incorporer la logique et des opérations à l'intérieur des restrictions de MySQL, envisagez cognant sur le code pour faire ce que vous voulez, et compter sur MySQL seulement pour le niveau le plus bas obtient / puts.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top