MySQL: mehrere Tabellen oder eine Tabelle mit vielen Spalten?

124

Das ist also eher eine Designfrage.

Ich habe einen Primärschlüssel (z. B. die Benutzer-ID) und diesem Benutzer sind unzählige Informationen zugeordnet.

Sollte ich mehrere Tabellen haben, die gemäß den Informationen in Kategorien unterteilt sind, oder sollte ich nur eine Tabelle mit vielen Spalten haben?

Früher hatte ich mehrere Tabellen, z. B. eine Tabelle für Anwendungsnutzungsdaten, eine Tabelle für Profilinformationen, eine Tabelle für Back-End-Token usw., um die Übersichtlichkeit zu gewährleisten.

Kürzlich sagte mir jemand, dass es besser ist, es nicht so zu machen und eine Tabelle mit vielen Spalten zu haben, ist in Ordnung. Die Sache ist, alle diese Spalten haben den gleichen Primärschlüssel.

Ich bin ziemlich neu im Datenbankdesign. Welcher Ansatz ist also besser und welche Vor- und Nachteile gibt es?

Wie geht das konventionell?

Xavier_Ex
quelle
Korrigieren Sie mich aus Gründen der Klarheit, wenn ich falsch
liege
1
Wird diese Datenbank für Analysezwecke oder für die operative / transaktionale Verarbeitung benötigt?
Alexander Radev

Antworten:

112

Jedes Mal, wenn Informationen eins zu eins sind (jeder Benutzer hat einen Namen und ein Kennwort), ist es wahrscheinlich besser, eine Tabelle zu haben, da dadurch die Anzahl der Verknüpfungen verringert wird, die die Datenbank zum Abrufen der Ergebnisse ausführen muss. Ich denke, einige Datenbanken haben eine Begrenzung für die Anzahl der Spalten pro Tabelle, aber ich würde mir im Normalfall keine Sorgen machen, und Sie können sie später jederzeit aufteilen, wenn Sie müssen.

Wenn die Daten eins zu viele sind (jeder Benutzer verfügt über Tausende von Zeilen mit Verwendungsinformationen), sollten sie in separate Tabellen aufgeteilt werden, um doppelte Daten zu reduzieren (doppelte Daten verschwenden Speicherplatz, Cache-Speicher und erschweren die Wartung der Datenbank ).

Vielleicht finden Sie den Wikipedia-Artikel zur Datenbanknormalisierung interessant, da er die Gründe dafür ausführlich beschreibt:

Bei der Datenbanknormalisierung werden die Felder und Tabellen einer relationalen Datenbank organisiert, um Redundanz und Abhängigkeit zu minimieren. Bei der Normalisierung werden normalerweise große Tabellen in kleinere (und weniger redundante) Tabellen unterteilt und Beziehungen zwischen ihnen definiert. Ziel ist es, Daten so zu isolieren, dass Hinzufügungen, Löschungen und Änderungen eines Feldes in nur einer Tabelle vorgenommen und dann über die definierten Beziehungen durch den Rest der Datenbank weitergegeben werden können.

Die Denormalisierung ist ebenfalls zu beachten, da es Fälle gibt, in denen das Wiederholen von Daten besser ist (da dadurch der Arbeitsaufwand für die Datenbank beim Lesen von Daten verringert wird). Ich würde dringend empfehlen, Ihre Daten zu Beginn so normal wie möglich zu gestalten und nur dann zu denormalisieren, wenn Sie Leistungsprobleme bei bestimmten Abfragen kennen.

Brendan Long
quelle
Vielen Dank für Ihre Antwort. Nachdem ich sie gelesen habe, habe ich wohl über die Eins-zu-Eins-Informationssituation gesprochen, in der ein Benutzer viele Eins-zu-Eins-Spalten hat.
Xavier_Ex
@Xavier_Ex - Ja, wenn es nur eine Spalte pro Benutzer gibt, ist es einfacher, mit nur einer großen Benutzertabelle zu arbeiten (und für die DB-Engine viel einfacher zu optimieren).
Brendan Long
Ihr bearbeiteter Beitrag enthält weitere hilfreiche Informationen! Ich habe ein neues Problem: Wenn einige der Spalten häufig aktualisiert werden, sollte ich sie in separate Tabellen einfügen? Beispielsweise wird das Geburtsdatum eines Benutzers nie aktualisiert, aber das Back-End-Token kann nach einer bestimmten Zeit ungültig werden und erfordert häufige Aktualisierungen. Wäre es besser, wenn ich die Tabellen auf diese Weise trenne, um die Leistung zu verbessern? Ich werde jetzt über das Wiki lesen, das du erwähnt hast :)
Xavier_Ex
@ Xavier_Ex - Ich würde es nicht empfehlen. Sie erzielen eine deutlich bessere Leistung, wenn Sie alle benötigten Daten in einer Tabelle nachschlagen können (siehe Denormalisierungsartikel). Joins sind teuer, weil (1) sie das Nachschlagen von Daten an mehreren Stellen erfordern, was Suchvorgänge auf einer sich drehenden Festplatte beinhalten kann, (2) im Allgemeinen mehrere Indizes und eine Art Zusammenführung erfordern und (3) die Abfrageplanung erschweren, was nicht der Fall ist Es braucht nur Zeit, erhöht aber auch die Wahrscheinlichkeit, dass der Abfrageoptimierer etwas falsch macht (und schlecht optimierte Abfragen können sehr langsam sein).
Brendan Long
1
Vor kurzem war ich mit demselben Problem konfrontiert, da MySQL InnoDB-Tabellen eine relativ kleine Längenbeschränkung haben (~ 8000 Bytes). In meiner Problemtabelle (Daten aus sehr langen Versicherungsformularen, mehr als 100 Spalten) haben wir mehrere Varchar-Spalten, alle UTF8. So haben wir das Limit von ~ 8000 Bytes problemlos gefüllt und die ganze Zeit "Fehler 139 von der Speicher-Engine" erhalten. Also mussten wir den Tisch teilen. (Wir haben mit dem neueren Barracuda-Format getestet und es hat ohne Aufteilung funktioniert, aber die Server unseres Clients verwenden weiterhin MySQL 5.0).
MV.
12

Ein großer Tisch ist oft eine schlechte Wahl. Verwandte Tabellen sind das, wofür relationale Datenbanken entwickelt wurden. Wenn Sie richtig indizieren und wissen, wie man performante Abfragen schreibt, werden sie gut funktionieren.

Wenn Tabellen zu viele Spalten enthalten, können Probleme mit der tatsächlichen Größe der Seite auftreten, auf der die Datenbank die Informationen speichert. Entweder ist der Datensatz zu groß für die Seite, wodurch Sie möglicherweise nicht in der Lage sind, einen bestimmten Datensatz zu erstellen oder zu aktualisieren, was Benutzer unglücklich macht, oder Sie können (zumindest in SQL Server) einen bestimmten Überlauf erhalten Datentypen (mit einer Reihe von Regeln, nach denen Sie suchen müssen, wenn Sie dies tun), aber wenn viele Datensätze die Seitengröße überschreiten, können Sie erhebliche Leistungsprobleme verursachen. Wie MYSQL nun mit den Seiten umgeht und ob Sie ein Problem haben, wenn die potenzielle Seitengröße zu groß wird, müssen Sie in der Dokumentation für diese Datenbank nachschlagen.

HLGEM
quelle
1
Ah verschiedene Stimmen! Welches ist immer toll. Danke für Ihre Information! Ich werde sicherstellen, dass ich mir dessen bewusst bin, wenn ich meine Tische mache ... aber ich wusste nicht, dass ich mich ursprünglich solcher Dinge auf niedrigem Niveau bewusst sein musste.
Xavier_Ex
4

Ich habe ein gutes Beispiel. Übermäßig normalisierte Datenbank mit den folgenden Beziehungen:

people -> rel_p2staff -> staff

und

people -> rel_p2prosp -> prospects

Wenn Personen Namen und Personendetails haben, hat das Personal nur die Personaldatensätze, die Interessenten nur die Interessentendetails und die rel-Tabellen sind Beziehungstabellen mit Fremdschlüsseln von Personen, die mit Mitarbeitern und Interessenten verknüpft sind.

Diese Art von Design wird für die gesamte Datenbank fortgesetzt.

Um diesen Satz von Beziehungen abzufragen, handelt es sich jedes Mal um einen Join mit mehreren Tabellen, manchmal um 8 und mehr Tabellen. Es hat bis Mitte dieses Jahres gut funktioniert, als es langsam wurde, nachdem wir 40000 Aufzeichnungen von Menschen hinter uns gelassen hatten.

Indizierung und alle niedrig hängenden Früchte waren im letzten Jahr aufgebraucht, alle Abfragen sind perfekt optimiert. Dies ist das Ende des Weges für das jeweilige normalisierte Design und Management, das nun eine Neuerstellung der gesamten Anwendung, die davon abhängt, sowie eine Umstrukturierung der Datenbank über einen Zeitraum von 6 Monaten genehmigt hat. $$$$ Autsch.

Die Lösung wird darin bestehen, eine direkte Beziehung zu people -> staffund zu habenpeople -> prospect

Vlad
quelle
Möchten Sie wissen, wie der Wiederaufbau verlaufen ist? Haben Sie am Ende etwas Ähnliches wie die Vererbung einzelner Tabellen entworfen, bei dem Sie ein typeWesen staffoder ein Wesen hatten prospect?
Coderama
1
Ging mit direkten Beziehungen Menschen -> Mitarbeiter und Menschen -> Interessenten, arbeitet einen Charme, einfach zu bedienen, schnell abzufragen.
Vlad
4

Als jemand, der MySQL häufig verwendete und kürzlich zu Postgres wechselte, war einer der großen Vorteile, dass Sie einem Feld in Postgres JSON-Objekte hinzufügen können.

Wenn Sie sich in dieser Situation befinden, müssen Sie sich nicht unbedingt zwischen einer großen Tabelle mit vielen Spalten entscheiden und diese aufteilen. Sie können jedoch Spalten in JSON-Objekte zusammenführen, um sie zu reduzieren, z. B. anstatt dass die Adresse 5 Spalten umfasst eins sein. Sie können dieses Objekt auch abfragen.

Moinhaque
quelle
Was ist mit der Leistung bei der Verwendung von JSON-Objekten während der Abfrage?
Dagalti
1
@dagalti die Leistung ist gut für die Anwendungen, auf denen ich es verwendet habe. Ich habe noch kein eigenes Benchmarking durchgeführt, aber dies könnte für Sie von Nutzen sein: arangodb.com/2018/02/…
moinhaque
3

Stellen Sie sich diese Fragen, wenn Sie alles in eine Tabelle einfügen. Haben Sie mehrere Zeilen für diesen Benutzer? Wenn Sie einen Benutzer aktualisieren müssen, möchten Sie einen Audit-Trail führen? Kann der Benutzer mehr als eine Instanz eines Datenelements haben? (wie zum Beispiel die Telefonnummer) Haben Sie einen Fall, in dem Sie später möglicherweise ein Element oder eine Reihe von Elementen hinzufügen möchten? Wenn Sie mit Ja antworten, möchten Sie höchstwahrscheinlich untergeordnete Tabellen mit Fremdschlüsselbeziehungen haben.

Vorteile von übergeordneten / untergeordneten Tabellen sind Datenintegrität, Leistung über Indizes (ja, Sie können dies auch für eine flache Tabelle tun) und IMO einfacher zu warten, wenn Sie später ein Feld hinzufügen müssen, insbesondere wenn es sich um ein erforderliches Feld handelt.

Nachteile Design ist schwieriger, Abfragen werden etwas komplexer

Es gibt jedoch viele Fälle, in denen ein großer flacher Tisch angemessen ist, sodass Sie sich Ihre Situation ansehen müssen, um eine Entscheidung zu treffen.

Brian
quelle
Danke, dass du mich erinnerst! In meinem Fall habe ich nur den Fall betrachtet, in dem jeder Benutzer nicht mehr als eine Zeile haben kann, sodass alle Informationsfelder eins zu eins sind. Außerdem kann der Benutzer nicht mehr als eine Instanz desselben Elements haben, da ich glaube, dass das Konzept eines Elements nicht an mehr als einer Stelle existieren kann. Bei der dritten Frage kann ich der Tabelle möglicherweise weitere Elemente hinzufügen, die jedoch die oben genannten Anforderungen nicht erfüllen. Ich denke, die Eltern / Kind-Tabelle ist gut, wenn ich einem Benutzer mehrere Zeilen zuordnen möchte, aber in diesem Fall ist mein Anliegen, dass ein Benutzer viele Eins-zu-Eins-Spalten hat.
Xavier_Ex
Selbst wenn alle Elemente derzeit eins zu eins sind, entfällt dadurch nicht die Notwendigkeit oder der Wunsch, übergeordnete / untergeordnete Tabellen IMO zu haben. Das Führen eines Protokolls geänderter Daten ist eine Verwendung. Das verzögerte Laden von Objekten ist eine andere. Während eine einzelne Tabellenstruktur Vorteile bietet, gibt es auch Vorteile für Eltern-Kind-Layouts (obwohl ich gesehen habe, dass die Leute auch damit extrem werden).
Brian
1

Ich bin schon mit einer Art Datenbankdesign fertig. Für mich hängt es von der Schwierigkeit des Systems bei der Datenbankverwaltung ab. Ja, es ist wahr, eindeutige Daten nur an einem Ort zu haben, aber es ist wirklich schwierig, Abfragen mit einer übermäßig normalisierten Datenbank mit vielen Datensätzen durchzuführen. Kombinieren Sie einfach die beiden Schemata. Verwenden Sie eine große Tabelle, wenn Sie das Gefühl haben, dass Sie massive Datensätze haben, die schwer zu pflegen sind, genau wie Facebook, Google Mail usw. und benutze eine andere Tabelle für einen Datensatz für ein einfaches System ... nun, das ist nur meine Meinung ... ich hoffe es könnte helfen ... mach es einfach ... du kannst es machen ... :)

Christopher
quelle
1
"Verwenden Sie eine große Tabelle, wenn Sie große Datensätze haben." Aber Facebook, Google speichert die Benutzerdaten nicht in einer einzigen Tabelle, sondern trennt sie so viele Tabellen.
Yami Odymel
0

Die herkömmliche Methode hierfür wäre die Verwendung unterschiedlicher Tabellen wie in einem Sternschema oder einem Schneeflockenschema. Ich würde diese Strategie jedoch auf zwei Gründe stützen. Ich glaube an die Theorie, dass Daten nur an einem Ort existieren sollten, da dort das von mir erwähnte Schema gut funktionieren würde. Ich bin jedoch auch der Meinung, dass ein Columnar-Ansatz für Reporting-Engines und BI-Suites von großem Vorteil wäre, da er die Reporting-Anforderungen besser unterstützt. Säulenansätze wie die mit infobright.org weisen enorme Leistungssteigerungen und Komprimierungen auf, was die Verwendung beider Ansätze unglaublich nützlich macht. Viele Unternehmen beginnen zu erkennen, dass nur eine Datenbankarchitektur in der Organisation nicht die gesamte Bandbreite ihrer Anforderungen unterstützt. Viele Unternehmen implementieren beide das Konzept, mehr als eine Datenbankarchitektur zu haben.

Craig Trombly
quelle
Vielen Dank für die Informationen, aber leider verstehe ich Ihre Antwort nicht ganz ... Ich werde nach den beiden Schemata suchen, die Sie zuerst erwähnt haben ...
Xavier_Ex
-4

Ich denke, eine einzelne Tabelle ist effektiver, aber Sie sollten sicherstellen, dass die Tabelle so organisiert ist, dass sie die Beziehung, den Trend sowie den Unterschied in den Variablen derselben Zeile anzeigt. Wenn die Tabelle beispielsweise das Alter und die Noten der Schüler anzeigt, sollten Sie die Tabelle so anordnen, dass der höchste Punktestand gut vom niedrigsten Punktestand unterschieden wird und der Altersunterschied der Schüler gleichmäßig ist.

user8081853
quelle