10 Stimmen

unnötige Normalisierung

Mein Freund und ich bauen gerade eine Website und haben eine große Meinungsverschiedenheit. Der Kern der Website ist eine Datenbank mit Kommentaren über "Menschen". Im Grunde können die Leute einen Kommentar abgeben und die Person angeben, um die es in dem Kommentar geht. Dann können die Betrachter die Datenbank nach Wörtern durchsuchen, die im Kommentar oder in Teilen des Namens der Person vorkommen. Die Datenbank ist vollständig nutzergeneriert. Wenn jemand zum Beispiel einen Kommentar zu einer falsch geschriebenen Version des Namens einer Person abgeben möchte, kann er das tun, und das ist auch in Ordnung. Es kann also sein, dass es mehrere Schreibweisen verschiedener Personen gibt, die in verschiedenen Einträgen aufgeführt sind (manche mit Mittelnamen, manche mit Spitznamen, manche falsch geschrieben usw.), aber das ist alles in Ordnung. Es ist uns egal, ob die Leute Kommentare über beliebige Personen oder imaginäre Personen abgeben.

Wie auch immer, es geht darum, wie wir die Datenbank strukturieren. Im Moment ist es nur eine Tabelle mit der Kommentar-ID als Primärschlüssel, und dann gibt es ein Feld für die "Person", über die der Kommentar ist:

Kommentar ID - Kommentar - Person

1 - "Er ist seltsam" - John Smith

2 - "stinkendes Mädchen" - Jenny

3 - "schwul" - John Smith

4 - "schuldet mir 20 Dollar" - Jennyyyyyyyyy

Alles funktioniert einwandfrei. Mit Hilfe der Datenbank kann ich Seiten erstellen, die alle "Kommentare" zu einer bestimmten "Person" auflisten. Er ist jedoch besessen davon, dass die Datenbank nicht normalisiert ist. Ich habe mich über Normalisierung informiert und herausgefunden, dass er sich geirrt hat. Die Tabelle IST derzeit normalisiert, weil die Kommentar-ID eindeutig ist und den "Kommentar" und die "Person" vorgibt. Jetzt besteht er darauf, dass "Person" eine EIGENE Tabelle haben sollte, weil sie ein "Ding" ist. Ich glaube nicht, dass das notwendig ist, denn obwohl die "Person" der größere Container ist (eine "Person" kann viele "Kommentare" über sie haben), scheint die Datenbank gut zu funktionieren, wenn die "Person" ein Attribut der Kommentar-ID ist. Ich verwende verschiedene PHP-Aufrufe für verschiedene SQL-Auswahlen, um die Ausgabe und die Art und Weise, wie der Benutzer suchen und Ergebnisse sehen kann, komplizierter erscheinen zu lassen, aber in Wirklichkeit ist der Aufbau recht einfach. Ich lasse die Benutzer nun Kommentare mit Daumen hoch und Daumen runter bewerten und führe eine "Punktzahl" als weiteres Feld in derselben Tabelle.

Meiner Meinung nach besteht derzeit keine Notwendigkeit für eine separate Tabelle für eindeutige "Personen"-Einträge, da die "Personen" keine eigene "Punktzahl" oder andere eigene Attribute haben. Das tun nur die Kommentare. Mein Freund besteht darauf, dass dies aus Effizienzgründen notwendig ist. Schließlich sagte ich: "OK, wenn du willst, dass ich eine separate Tabelle anlege und 'Person' ein eigenes Feld ist, was wäre dann das zweite Feld? Denn wenn eine Tabelle nur eine einzige Spalte hat, erscheint sie sinnlos. Ich stimme zu, dass wir später vielleicht eine eigene Tabelle für 'Person' brauchen, aber das können wir dann regeln. Er sagte dann, dass Zeichenketten keine Primärschlüssel sein können und dass wir die "Personen" in der aktuellen Tabelle in Zahlen umwandeln würden, und die Zahlen würden der Primärschlüssel in der neuen Tabelle "Person" sein. Dies erscheint mir unnötig und würde die Lesbarkeit der aktuellen Tabelle erschweren. Er ist auch der Meinung, dass es unmöglich sein wird, die zweite Tabelle später zu erstellen, und dass wir jetzt schon vorhersehen müssen, dass wir sie später für etwas brauchen könnten.

Wer hat Recht?

1voto

Erik Funkenbusch Punkte 91649

Nun, es gibt zwei Denkansätze. Die eine besagt, dass Sie Ihr Datenmodell so normalisiert wie möglich erstellen und dann de-normalisieren sollten, wenn Sie mehr Effizienz benötigen. Die andere besagt im Grunde, dass man das Minimum an Arbeit leisten sollte, das für die Aufgabe notwendig ist, und es dann ändern sollte, wenn sich die Anforderungen ändern. Auch bekannt als YAGNI (You aren't going to need it).

Es hängt alles davon ab, wohin die Reise gehen soll. Wenn das alles ist, was es sein wird, dann ist Ihr Ansatz wahrscheinlich in Ordnung. Wenn Sie beabsichtigen, es im Laufe der Zeit mit neuen Funktionen zu verbessern, dann hat Ihr Freund recht.

1voto

NealB Punkte 16282

Bei der Normalisierung geht es um funktionale Abhängigkeiten (FDs). Sie müssen identifizieren todos der FD's, die unter den Attributen Ihres Datenmodells existieren, bevor es vollständig normalisiert werden kann.

Lassen Sie uns überprüfen, was Sie haben:

  • Jede beliebige Instanz einer CommentId bestimmt funktionell die Person (FD: CommentId -> Person )
  • Jede beliebige Instanz eines CommentId bestimmt funktionell die Comment (FD: CommentId -> Comment )
  • Jede beliebige Instanz einer CommentId bestimmt funktionell die UserId (FD: CommentId -> UserId )
  • Jede beliebige Instanz eines CommentId bestimmt funktionell die Score (FD: CommentId -> Score )

Alles hier ist ein abhängiges Attribut von CommentId et CommentId allein. Dies könnte Sie zu der Annahme verleiten, dass eine Beziehung (Tabelle), die alle oder eine Teilmenge der obigen Attribute enthält, normalisiert werden muss.

Als erstes sollten Sie sich fragen, warum Sie die CommentId Attribut überhaupt? Streng genommen, ist dies ein hergestelltes Attribut - es bezieht sich auf nichts "Echtes". CommentId ist gemeinhin als Surrogatschlüssel bezeichnet. Ein Ersatzschlüssel ist einfach ein erfundener Wert, der für für eine eindeutige Wertemenge steht, die einer anderen Gruppe von Attributen entspricht. Welche Gruppe von Attributen ist also CommentId ein Surrogat für? Das können wir herausfinden herausfinden, indem wir die folgenden Fragen stellen und dem Modell neue FDs hinzufügen:

  • 1) Muss ein Kommentar einzigartig sein? Wenn ja, muss der FD: Comment -> CommentId muss wahr sein.
  • 2) Kann ein und derselbe Kommentar mehrmals abgegeben werden, solange er sich auf eine andere Person bezieht? Wenn ja, dann FD: Person + Comment -> CommentId muss wahr sein und der FD in 1 oben ist falsch.
  • 3) Kann ein und derselbe Kommentar mehrmals über dieselbe Person abgegeben werden, vorausgesetzt, er wurde abgegeben von verschiedenen UserId's? Wenn ja, können die FDs in 1 und 2 nicht wahr sein, sondern FD: Person + Comment + UserId -> CommentId kann wahr sein.
  • 4) Kann ein und derselbe Kommentar mehrmals über dieselbe Person von derselben UserId abgegeben werden, aber unterschiedliche Bewertungen haben? Dies impliziert FD: Person + Comment + UserId ' + Score -> CommentId ist wahr und die anderen sind falsch.

Genau einer der 4 oben genannten FD's muss wahr sein. Welcher davon zutrifft, wirkt sich darauf aus, wie Ihr Datenmodell normalisiert wird.

Angenommen, FD: Person + Comment + UserId -> CommentId sich als wahr herausstellt. Die logischen Konsequenzen sind das:

  • Person + Comment + UserId y CommentId dienen als gleichwertige Schlüssel in Bezug auf Score
  • Score sollte in eine Beziehung mit einem, aber nicht mit beiden Schlüsseln gesetzt werden (um transitive Abhängigkeiten zu vermeiden). Die offensichtliche Wahl wäre CommentId da es speziell als Surrogat geschaffen wurde.
  • Eine Beziehung, die aus: CommentId , Person , Comment , UserId ist erforderlich, um die Schlüssel mit seinem Surrogat zu verbinden.

Vom theoretischen Standpunkt aus betrachtet, ist der Surrogatschlüssel CommentId ist nicht nicht erforderlich, damit Ihr Datenmodell oder Ihre Datenbank funktioniert. Sein Vorhandensein kann jedoch die Konstruktion von Beziehungen beeinflussen.

Die Erstellung von Ersatzschlüsseln ist eine praktische Frage von einiger Bedeutung. Überlegen Sie, was passieren könnte, wenn Sie keinen Surrogatschlüssel verwenden, sondern das vollständige Attributsatz Person + Comment + UserId an seiner Stelle, insbesondere wenn es erforderlich war in mehreren Tabellen als Fremd- oder Primärschlüssel benötigt wird:

  • Kommentar könnte viel Platz in der Luft schaffen in Ihrer Datenbank, da er in mehreren Tabellen wiederholt wird. Er ist wahrscheinlich mehr als nur ein paar Zeichen lang.
  • Was passiert, wenn jemand einen Kommentar bearbeiten möchte? Diese Änderung muss weitergegeben werden auf alle Tabellen übertragen werden, in denen Kommentar Teil eines Schlüssels ist. Kein schöner Anblick!
  • Die Indizierung langer, komplexer Schlüssel kann viel Platz beanspruchen und/oder zu einer langsamen Aktualisierungsleistung führen

Der einem Surrogatschlüssel zugewiesene Wert ändert sich nie, egal was Sie mit den Werten machen die mit den Attributen verbunden sind, die er bestimmt. Die Aktualisierung der abhängigen Attribute ist nun auf die eine Tabelle beschränkt, die den Surrogatschlüssel definiert. Dies ist von großer praktischer Bedeutung.

Nun zurück zu der Frage, ob Sie ein Surrogat erstellen sollten für Person . Hat Person live auf der linken Seite von vielen oder allen FDs? Wenn dies der Fall ist, wird sich sein Wert in Ihrer Datenbank verbreiten, und es spricht einiges dafür, ein Surrogat für sie zu erstellen. Ob es sich bei "Person" um ein Textattribut oder ein numerisches Attribut handelt, ist für die Wahl eines Ersatzschlüssels unerheblich.

Ausgehend von dem, was Sie gesagt haben, gibt es bestenfalls ein schwaches Argument für die Schaffung eines Surrogat für Person . Dieses Argument stützt sich auf die Vermutung, dass sein Wert irgendwann in der Zukunft zu einem Schlüssel oder Teil eines Schlüssels werden könnte.

1voto

HLGEM Punkte 91543

Wenn Sie nie die Absicht haben, die Personenspalte mit einem Benutzer oder etwas anderem zu verknüpfen, und die Daten offensichtlich keine Konsistenz- oder Datenintegritätsprüfungen benötigen, warum ist sie dann überhaupt in einer relationalen Datenbank? Wäre dies nicht ein Anwendungsfall für eine nosql-Datenbank? Oder übersehe ich etwas?

0voto

Aaron Punkte 7281

So sieht es aus. Wenn Sie etwas schaffen, sollten Sie dafür sorgen, dass es Raum zum Wachsen hat. Sie sollten versuchen, zukünftige Projekte und Weiterentwicklungen Ihres Programms zu antizipieren. In diesem Szenario haben Sie Recht, wenn Sie sagen, dass derzeit kein Bedarf besteht, eine Personentabelle hinzuzufügen, die nur ein Feld enthält (die ID nicht mitgerechnet, vorausgesetzt, Sie haben ein int ID-Feld und einen Personennamen). In der Zukunft werden Sie jedoch vielleicht andere Attribute für diese Personen haben wollen, wie Vorname, Nachname, E-Mail-Adresse, Datum des Hinzufügens usw.

Während eine Übernormierung sicherlich schädlich ist, würde ich persönlich eine weitere, größere Tabelle erstellen, um die Person mit zusätzlichen Feldern zu speichern, so dass ich in Zukunft leicht neue Funktionen hinzufügen kann.

0voto

zMan Punkte 3049

Wann immer Sie mit Benutzern zu tun haben, sollte es eine spezielle Tabelle geben. Dann können Sie die Tabellen einfach verknüpfen und auf die ID des Benutzers verweisen.

user -> id | username | password | email

comment -> id | user_id | content

SQL, um die Kommentare mit den Benutzern zu verbinden:

SELECT user.username, comment.content FROM user JOIN comment WHERE user.id = comment.user_id;

Das wird es in Zukunft viel einfacher machen, wenn Sie Informationen über einen bestimmten Benutzer suchen wollen. Der zusätzliche Aufwand ist vernachlässigbar.

Was die "Punktzahl" für jeden Kommentar betrifft, so sollte dies ebenfalls in einer separaten Tabelle erfolgen. Auf diese Weise können Sie einen Nutzer mit einem "Like" oder "Dislike" verbinden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X