Likes oder Stimmen für Beiträge

10

Ich mache ein kleines Programm, in dem Benutzer Beiträge verfassen oder Blogs schreiben. Auf diesen Posts können andere Benutzer den Post wie in Facebook mögen oder nicht mögen oder den Post wie im Stackoverflow hoch- oder runterstimmen. Ich würde gerne eine gute Datenbankstruktur kennen, die häufig verwendet wird und das Programm arbeitet effizient mit dieser Struktur. Ich habe zwei Möglichkeiten

Zuerst

Post:

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

In obiger Weise idist die Postid. In der Likes-Spalte 1,2,3befindet sich die Benutzer-ID, die den Beitrag oder das Blog gemocht oder positiv bewertet hat. 7,55,44,3ist die ID der Benutzer, die den Beitrag oder das Blog nicht mochten oder ablehnten.

Zweite

Post:

id    head  message   datepost
1     ab    anchdg     DATE

Likes:

id    postid    userid
1       1         1
2       2         2

Abneigungen:

id    postid    userid
1       1         7
2       1         55

Auf diese Weise muss ich zwei separate Tabellen für Likes und Dislikes erstellen, um die Likes von Posts zu erhalten. Auf diese Weise werden die Tabellen dh Likes& Dislikesstark gefüllt. Dies kann die Tabelle schwer und die Verarbeitung langsam machen.

Ich würde gerne wissen, wie diese Aufgabe besser und standardisierter gelöst werden kann.

Harshit Shrivastava
quelle
4
Ich gehe davon aus, dass ein Benutzer einen Beitrag nicht mögen und nicht mögen kann . Wenn ja, hätte ich eine Tabelle für Vorlieben und Abneigungen mit einer BIT-Spalte (1 für "Gefällt mir", 0 für "Gefällt mir nicht").
Dwjv
1
Oder 1 und -1 für einfachere Summen
jkavalik
1
@dwjv Im ersten Beispiel hat Benutzer 3 den Beitrag tatsächlich gemocht und nicht gemocht.
Dan Henderson

Antworten:

20

Das Problem, mit dem Sie konfrontiert sind, wird als "Normalform" von Datenbanken bezeichnet, insbesondere als erste Normalform. https://en.wikipedia.org/wiki/First_normal_form .

Ihre Datenbank mit den verketteten Benutzer-IDs (erste Version) befindet sich nicht in der ersten normalen Form.

Unter https://en.wikipedia.org/wiki/Database_normalization erfahren Sie, warum und wie Normalisierung im Allgemeinen als gut angesehen wird.

In Ihrem ersten Beispiel wird die Abfrage nach "Benutzer 4 mag den Beitrag nicht mehr" kompliziert. Es müssen Zeichenfolgenoperationen ausgeführt werden, bei denen Nebenwirkungen und Eckfälle berücksichtigt werden müssen (Benutzer ist der einzige Benutzer, der "gefällt", Benutzer ist der Benutzer, der zuletzt gefällt, Benutzer befindet sich in der Mitte der Zeichenfolge "Gefällt mir"). Ich würde das schlecht finden. Tu es nicht. Verwenden Sie ein normalisiertes Design.

re: Datenbank wird schwer

Wenn Sie einen Beitrag mit 4 Millionen Likes haben, haben Sie in Datenbankdesign 1 eine Zeile mit einer "Likes" -Spalte, die mindestens 4 Millionen Zeichen breit ist (da Sie das Komma als Trennzeichen benötigen). Sie müssen dann Zeichenfolgenoperationen für Zeichenfolgen mit einer Breite von vier Millionen Ziffern ausführen. Dies ist sehr unperformant und langsam.

Andererseits sind Datenbanken für die Verarbeitung von Millionen von Zeilen ausgelegt. Wir haben Datenbanken mit mehreren hundert Millionen Zeilen und count () - Operationen sind schnell. Extrem schnell. Nein, dies ist kein Leistungsengpass.

Das nächste Problem wäre Lesbarkeit und Wartbarkeit.

Sagen Sie mir zum Beispiel, was diese beiden Aussagen bewirken:

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
til_b
quelle
Wie ich bereits erwähnte, würde der Tisch dann nicht schwer werden, wenn Crores oder Milliarden von Likes in der Tabelle vorhanden wären? Würde es nicht viel Zeit in Anspruch nehmen, eine Tabelle mit unzähligen Aufzeichnungen zu durchsuchen, da die Tabelle sehr schnell gefüllt wird?
Harshit Shrivastava
6
@HarshitShrivastava mysql kann einfache Tabellen mit Milliarden Zeilen verarbeiten, aber stellen Sie sich diese Milliarden (Abneigungen) als Zeichenfolgen in Ihrer Benutzertabelle vor - das könnte sogar noch größer und schwieriger zu bearbeiten sein.
Jkavalik
3
Eine Sache, die @til_b nicht direkt erwähnt (aber normalerweise durch die Verwendung normaler Formulare impliziert wird), ist, dass das zweite Design, das ordnungsgemäß implementiert wurde, es dem zugrunde liegenden Datenbankmodul ermöglicht, die referenzielle Integrität aufrechtzuerhalten, was mit dem ersten Entwurfsmuster nicht möglich ist. Das bedeutet im Wesentlichen, dass die Datenbank verknüpfte Daten löscht, wenn Benutzer 4 gelöscht wird, da sie weiß, welche Datensätze vom Benutzer 4-Datensatz abhängen. Das erste Design ist dazu nicht in der Lage, da die Datenbank nicht intuitiv weiß, wie die Beziehung in der Zeichenfolge verwaltet wird.
David Antaramian
9

Der zweite Weg ist viel besser, da Sie leicht ein Like / Dislike hinzufügen oder entfernen können.

Sie sollten Ihre zweite Lösung jedoch ändern, indem Sie eine Tabelle für "Gefällt mir" oder "Gefällt mir nicht" verwenden.
Die Spalten der Like / Dislike-Tabelle sollten id, postid, userid und eine andere für den Wert eines Like oder Dislike sein, z. B. 1 für Dislike und -1 für Like.

Legen Sie post_id und user_id als zusammengesetzten Primärschlüssel fest und es funktioniert einwandfrei.

Die Größe des Tisches wächst mit der Zeit. Sie haben jedoch nur zwei echte Spalten. Die ID und der Wert des Like / Dislike. Die Post-ID und die Benutzer-ID sind nur damit verknüpft und in Ihrer Benutzer- und Post-Tabelle gespeichert.

Julian S.
quelle
3
Sie sollen user_id, post_idund valuein der Tabelle. Keine separate idSpalte erforderlich .
Jkavalik
3
Wie aus dem Kommentar von @ jkavalik zu der Frage hervorgeht, wären 1 und -1 wahrscheinlich bessere Werte für "Gefällt mir" und "Nicht mögen" als 1 und 2, da dies die Berechnung einer Gesamtpunktzahl über eine einfache Tabellensumme ermöglichen würde, anstatt die Anzahl von zu subtrahieren Zeilen mit "2" aus der Anzahl der Zeilen mit "1".
Dan Henderson
@DanHenderson: So etwas wie Likes - Abneigungen könnten viel schneller sein als eine Summe. (Das heißt, es würde aber auch mit 1 und -1
funktionieren
Wie würden Sie das tun, wenn Sie zwei weitere Aktionen wie Liebe und Wut gesagt hätten? Ich meine die 1 für Likes und -1 für Abneigungen mit 2 weiteren Aktionen
PirateApp
Wenn Sie nichts wollen, sumkönnen Sie Liebe = 2 und Wut = 3 setzen
Julian S