Aime ou vote pour les messages


10

Je fais un petit programme où les utilisateurs font des publications ou écrivent des blogs. Sur ces publications, les autres utilisateurs peuvent aimer ou détester la publication comme dans Facebook ou voter positivement ou défavorablement la publication comme dans stackoverflow. Je voudrais connaître une bonne structure de base de données qui est couramment utilisée et le programme fonctionne efficacement avec cette structure. J'ai deux options

Première

Publier:

id   head   message   datepost   likes   dislikes
1     ab    anchdg     DATE      1,2,3   7,55,44,3

De la manière ci-dessus, idest le postid. Dans la colonne " 1,2,3J'aime" , se trouve l'ID de l'utilisateur qui a aimé ou surévalué le message ou le blog. 7,55,44,3est l'identifiant des utilisateurs qui n'aiment pas ou ont voté contre le message ou le blog.

Seconde

Publier:

id    head  message   datepost
1     ab    anchdg     DATE

Aime:

id    postid    userid
1       1         1
2       2         2

N'aime pas:

id    postid    userid
1       1         7
2       1         55

De cette façon, je dois créer deux tableaux distincts pour les likes et les likes pour obtenir les likes de la publication. De cette façon, les tables ie Likes& Dislikesseront fortement remplies. Cela pourrait rendre la table lourde et le traitement lent.

Donc, je voudrais savoir quelle est la meilleure et la meilleure façon d'accomplir cette tâche?


4
Je suppose qu'un utilisateur ne peut pas aimer et détester un message? Si c'est le cas, j'aurais une table pour les likes et les likes, avec une colonne BIT (1 pour like, 0 pour dislike).
dwjv

1
Ou 1 et -1 pour des sommes plus faciles
jkavalik

1
@dwjv Dans le premier exemple, l'utilisateur 3 a en fait aimé et détesté le message.
Dan Henderson

Réponses:


20

Le problème que vous rencontrez est connu sous le nom de "formes normales" de bases de données, en particulier la première forme normale. https://en.wikipedia.org/wiki/First_normal_form .

Votre base de données avec les ID utilisateur concaténés (première version) n'est pas sous sa première forme normale.

Voir https://en.wikipedia.org/wiki/Database_normalization pour savoir pourquoi et comment la normalisation est généralement considérée comme bonne.

Dans votre premier exemple, la requête pour "l'utilisateur 4 n'aime plus la publication" devient compliquée. Il devra effectuer des opérations de chaîne, qui devront prendre en compte les effets secondaires et les cas d'angle (l'utilisateur est le seul utilisateur "aimant", l'utilisateur est le dernier utilisateur aimant, l'utilisateur est au milieu de la chaîne utilisateur aimante). Je trouverais ça mauvais. Ne le fais pas. Utilisez une conception normalisée.

re: la base de données devient lourde

Si vous avez une publication qui a 4 millions de likes, dans la conception de la base de données 1, vous auriez une ligne avec une colonne "likes" d'au moins 4 millions de caractères (car vous aurez besoin de la virgule comme caractères séparateurs). Vous devrez ensuite effectuer des opérations de chaîne sur quatre millions de chaînes de chiffres. C'est très peu performant et lent.

D'un autre côté, les bases de données sont conçues pour gérer des millions de lignes. Nous avons des bases de données avec plusieurs centaines de millions de lignes et count () - les opérations sont rapides. Extrêmement vite. Donc non, ce ne sera pas un goulot d'étranglement en termes de performances.

Le prochain problème serait la lisibilité et la maintenabilité.

Par exemple, dites-moi ce que font ces 2 déclarations:

select count(*)
from posts
inner join likes on posts.postid = likes.postid
where postid = 7

select len(likes) - len(replace(likes, ',', ''))
from posts
where postid = 7

Comme je l'ai mentionné, si des crores ou des milliards de goûts sont présents dans le tableau, le tableau ne deviendrait-il pas lourd? Cela ne prendrait-il pas beaucoup de temps pour rechercher une table avec des dizaines de records puisque la table sera remplie très rapidement?
Harshit Shrivastava

6
@HarshitShrivastava mysql peut gérer de simples tables de milliards de lignes, mais imaginez ces milliards (dis) likes comme chaînes dans votre table d'utilisateurs - qui pourraient être encore plus gros et difficiles à travailler.
jkavalik

3
Une chose que @til_b ne mentionne pas directement (mais qui est généralement impliquée par l'utilisation de formulaires normaux) est que la deuxième conception, correctement implémentée, permettra au moteur de base de données sous-jacent de maintenir l'intégrité référentielle, ce qui ne peut être fait avec le premier modèle de conception. Cela signifie essentiellement que si l'utilisateur 4 est supprimé, la base de données effacera les données liées car elle sait quels enregistrements dépendent de l'enregistrement de l'utilisateur 4. La première conception est incapable de cela car la base de données ne sait pas intuitivement comment gérer la relation dans la chaîne.
David Antaramian

9

La deuxième façon est bien meilleure, car vous pouvez facilement ajouter ou supprimer un J'aime / Je n'aime pas.

Mais vous devez modifier votre deuxième solution en utilisant une table pour aimer ou ne pas aimer.
Les colonnes de la table like / dislike doivent être id, postid, userid et une autre pour la valeur de like ou dislike, par exemple 1 pour dislike et -1 pour like.

Définissez post_id et user_id comme clé primaire composite et cela fonctionne très bien.

La taille de la table augmentera avec le temps. mais vous ne disposez que de deux colonnes réelles. L'identifiant et la valeur de ce que j'aime / ce que je n'aime pas. Le postid et l'ID utilisateur ne sont liés qu'à lui et stockés dans votre table utilisateur et poste.


3
Vous devriez avoir user_id, post_idet valuedans le tableau. Pas besoin d'une idcolonne séparée .
jkavalik

3
Comme l'a suggéré le commentaire de @ jkavalik sur la question, 1 et -1 seraient probablement de meilleures valeurs pour j'aime et n'aime pas que 1 et 2, car cela permettrait de calculer un score total au moyen d'une simple somme de tableau, plutôt que de soustraire le nombre de lignes avec "2" à partir du nombre de lignes avec "1".
Dan Henderson

@DanHenderson: Quelque chose comme les goûts - les aversions pourraient être un peu plus rapides qu'une somme. (Cela dit, cependant, cela fonctionnerait également avec 1 et -1.)
cHao

voté, comment feriez-vous si vous aviez dit 2 actions supplémentaires comme l'amour et la colère? je veux dire le 1 pour les goûts et -1 pour les aversions avec 2 autres actions
PirateApp

Si vous ne voulez sumrien, vous pouvez définir l'amour = 2 et la colère = 3
Julian S
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.