7
votes

Stockage des données hiérarchiques (MySQL) pour le marketing de référence

Je dois avoir une hiérarchie de 5 niveaux pour les utilisateurs enregistrés sur un site Web. Chaque utilisateur est invité par un autre et je dois connaître tous les descendants d'un utilisateur. Et aussi les ancêtres d'un utilisateur.

J'ai en tête 2 solution. p>

  1. Garder une table avec des relations de cette façon. Une table de fermeture: li> OL>
       user_id ancestor_level1_id ancestor_level2_id ancestor_level3_id ancestor_level4_id ancestor_level5_id
       10      9                  7                  4                  3                  2
       9       7                  4                  3                  2                  1
    


3 commentaires

Cela aiderait si vous avez défini «bon» - recherchez-vous une vitesse, une flexibilité, une facilité d'entretien?


@Neville Je cherche la vitesse, la facilité d'entretien mais aussi une certaine flexibilité


@Neville, @ Morandi3: Nous devons savoir exactement quels types de questions vous voulez accomplir.


4 Réponses :


2
votes

Gestion des données hiérarchiques dans MySQL

En général, j'aime la "couche imbriquée", en particulier Dans MySQL, qui n'a pas vraiment de prise en charge de la langue pour les données hiérarchiques. C'est rapide, mais vous devrez vous assurer que vos développeurs ont lu cet article si la facilité d'entretien est une grosse affaire. C'est très flexible - ce qui ne semble pas compter beaucoup dans votre cas.

Cela semble être bon pour votre problème - dans le modèle de référence, vous devez trouver l'arborescence des référeuses, qui est rapide dans le modèle de jeu imbriqué; Vous devez également savoir qui sont les ~ enfants @ d'un utilisateur donné et la profondeur de leur relation; Ceci est aussi rapide.


1 commentaires

Je ne pense pas que ce soit une bonne approche pour mon système, car l'ensemble imbriqué doit être mis à jour à chaque fois lorsqu'un nouvel utilisateur inscrit, n'est-ce pas ?!



4
votes

Utilisez le moteur de stockage OQGRAPH.

Vous voulez probablement garder une trace d'un nombre EM> arbitraire EM>, plutôt que de 5 niveaux. Obtenez l'une des fourches MySQL prenant en charge le Moteur QGraph (telle comme Mariah ou Ourdelta), et utilisez-le pour stocker votre arbre. Il met en œuvre le modèle de liste des adjacents, mais en utilisant une colonne spéciale appelée loquet code> pour envoyer une commande au moteur de stockage, indiquez-lui quel type de requête à effectuer, vous obtenez tous les avantages d'une table de fermeture Sans avoir besoin de faire le travail de la comptabilité chaque fois que quelqu'un enregistre pour votre site. P>

Voici les questions que vous utiliseriez à OQgraph. Voir la documentation à http://openquery.com/graph-computation-Engine-Documentation P>

Nous allons utiliser l'origine comme le référent et le déstaide comme référence. p>

Pour ajouter l'utilisateur 11, référé par l'utilisateur 10 P>

SELECT count(linkid), weight
FROM ancestors_table
WHERE latch = 2 AND origid = 3
GROUP BY weight;


8 commentaires

@Ken je ne sais pas si c'est une bonne idée de garder un nombre de niveaux "arbitraire", disons que nous aurons environ 100 niveaux. Est-ce une bonne idée de garder tous ces niveaux dans la base de données?


@ Morandi3: Ne cherchez que les contraintes techniques (sans avoir discuté des implications de la vie privée), cela dépend de la façon dont vous le faites. Votre table des ancêtres utilise des espaces de stockage proportionnels au nombre maximal de niveaux que vous suivez. OQGraph est un moteur de stockage destiné à la réalisation d'algorithmes de graphes. Il est conçu pour effectuer des opérations telles que l'algorithme de chemin le plus court de Dijkstra qui sont normalement difficiles ou impossibles dans une base de données SQL, en ayant une colonne spéciale dans la table pour émettre une commande sur le moteur de stockage. Il n'a pas la même pénalité spatiale.


@Ken Je ne suis pas sûr de pouvoir utiliser Mariadb ou Ourdelta sur mon serveur. Est-il possible d'utiliser ce moteur uniquement pour une table de la base de données ou je dois changer de stockage pour toutes les tables? Laquelle de mes idées a l'air la plus rapide / fiable dans votre opionion?


@ Morandi3: Vous n'avez pas besoin de changer de stockage pour toutes vos tables. Un moteur de stockage dans MySQL est un plugin de création et de gestion d'un type de table particulier. Le type de table par défaut dans MySQL est MyISAM et la distribution par défaut vous permet également de créer des tables particulières avec le moteur de stockage Innodb (pour une meilleure concurrence dans les transactions). OQGraph est juste un autre type de table que vous pouvez créer lorsque le besoin se pose. Il ne change pas la valeur par défaut, il ne modifie pas le moteur de stockage utilisé pour les tables existantes et il ne remplace les moteurs de stockage par défaut.


@ Morandi3: Pour savoir quoi de neuf, je devrais savoir quels types de questions que vous vouliez effectuer. Je ne pense pas que le modèle de jeu imbriqué fonctionnera bien pour vous puisque vous avez beaucoup d'insertions. Si vous envisagez fermement la table de relations à 5 niveaux, il peut simplifier les choses d'utiliser une chaîne d'ancêtres délimitée au lieu de 5 colonnes distinctes.


@Ken nous aurons des questions pour: Ajout d'un nouvel utilisateur, donnant des commissions (pourcentage) aux ancêtres lorsqu'un descendant achète quelque chose, chaque utilisateur peut savoir combien de descendants ont sur chaque niveau (pour cela, je pense à utiliser des champs dans Base de données: Count_Level1, Count_Level2, où conserver ces informations. Oui, une chaîne d'ancêtres délimitées devrait être bien lorsque j'ai besoin de découvrir les ancêtres, mais je dois trouver également pour chaque utilisateur les descendants.


@ Morandi3: J'ai maintenant 2 réponses qui précisent exactement comment faire chacune de vos questions. Aucun de ces modèles n'est très compliqué.


@ Morandi3: N'oubliez pas d'accepter quelle que soit la réponse que vous avez décidée de l'utiliser, en cliquant sur la coche en regard de la réponse.



1
votes

Chaîne délimitée d'ancêtres

Si vous envisagez vivement de la table de relations à 5 niveaux, il peut simplifier des éléments d'utiliser une chaîne d'ancêtres délimitée au lieu de 5 colonnes distinctes. P>

select
   depth-(select depth from ancestors_table where user_id=3),
   count(*)
from ancestors_table
where ancestors like '%,3,%' or ancestors like '3,%' or ancestors like '%,3'
group by depth;


12 commentaires

@Ken "ancêtres" Le champ ne devrait pas être dans ce cas «Descendants»? Ou pour ce que nous utilisons "profondeur"? Parce que chaque utilisateur n'a qu'un ancêtre à chaque niveau.


@ Morandi3: Dans la dernière requête, vous recherchez des "nœuds qui ont 3 ans comme ancêtre" et le regroupant à quel point ils sont de loin en dessous de ce nœud. La colonne de profondeur garde une trace du nombre d'ancêtres d'un certain nœud, le regroupant en niveaux dans la base de données.


@Ken oui, mais un utilisateur n'a qu'un ancêtre / niveau


@ Morandi3: Je pense que vous êtes déroutant parent avec ancêtre . L'utilisateur 10 n'a qu'un parent (utilisateur 9). Et l'utilisateur 9 possède un parent (utilisateur 7). L'utilisateur 7 a également un parent (utilisateur 4). Tous ces parents et parents de parents sont appelés "ancêtres" de l'utilisateur 10. La profondeur est donc le nombre de sauts que vous devez aller avant d'atteindre quelqu'un qui n'a pas été référé par un ami (quelqu'un qui a trouvé votre site par une publicité ou une recherche aléatoire).


@Ken Ok, maintenant je comprends, la profondeur est la longueur de la chaîne. HMM, mais avec cette solution est difficile à trouver des descendants pour un utilisateur.


@Morandi: Trouver les descendants est la deuxième requête. (N'oubliez-vous que comme les ancêtres, les descendants sont des enfants et des enfants d'enfants, etc.) Vous voulez dire trouver simplement les enfants?


@Ken ce que je voulais dire, c'est que: trouver des descendants pour un niveau spécifique sera lent car nous ne pouvons pas utiliser un index pour cette


@ Morandi3: Umm Ouais. C'est l'inconvénient de ce modèle. (Vous pourrait mettre un index sur le champ de profondeur , mais je doute que cela aidait beaucoup.) C'est fondamentalement pourquoi SQL et les graphiques / les arbres ne se mélangent pas, en un mot et pourquoi le moteur de stockage OQGraph a été inventé.


@Ken hmm, oui, oqgraph semble une bonne solution. Pensez-vous qu'une table de fermeture (Ancestor_id descendant_id) ou utiliser 5 champs, une pour chaque niveau ralentira beaucoup les choses?


@ Morandi3: Je pense que l'utilisation de 5 champs sera très difficile à travailler. Je posterai une réponse à la façon de faire des choses avec une table de fermeture cependant, et vous pouvez décider si cela fonctionnera.


@ Morandi3: La table de fermeture a l'air viable, si vous n'êtes pas inquiet de l'évêsif de l'espace qui vient de la liste de chaque ancêtre à plusieurs reprises.


@Ken: Je suis un peu inquiet, car pour 50 000 utilisateurs, nous aurons une table avec environ 300 000 rangées.



10
votes

Table de fermeture
select ancestor_id, distance from ancestor_table where descendant_id=10;


1 commentaires

Toutes vos solutions sont bonnes: D Il est difficile de trouver le meilleur. Je pense que je choisirai ceci pour l'instant. Mais aussi le moteur de stockage OQGraph semble être une solution fiable. Merci