Datenbank Architektur Frage
Kathrin
- datenbank
Hi!
Ich arbeite an einer Social-Networking-Seite, kennen wir ja alle sowas...
Ich erwarte zwar nicht, daß die Website so groß wie facebook wird, aber die Datenbank Architektur sollte trotzdem stimmen.
Jedenfalls habe ich folgendes Problem:
Jeder User hat 2 Tables:
Im ersten Table stehen die Kontakte des Users:
-Usernamen der anderen User (mit denen dieser User Kontakt hat)
-Art des Kontakts (1=Freunde,2=Blockiert,3=Bookmark)
Im zweiten Table stehen die Nachrichten für diesen User:
-timestamp (wann die Nachricht eingegangen ist)
-ob sie neu oder gelesen ist (0 oder 1)
-von wem sie kommt (Username)
-und die eigentliche Nachricht natürlich (text)
Als ich mit dem Projekt begonnen habe, dachte ich noch, alle Nachrichten für alle User in einem Table speichern ist doch total doof.
Jetzt denke ich allerdings, bei 1 Million User wären in dieser Datenbank 2 Millionen Tables, und das ist ja noch doofer. :-(
Vielleicht sollte ich die User alphabetisch ordnen.
Und alle Usernamen die mit A anfangen speichern ihre Nachrichten im Table messages_A und alle User mit B in messages_B.
Und für die Kontakte dann genauso...
Was denkt ihr?
Habt ihr Erfahrung mit sowas?
Wie macht man sowas professionel?
Danke schonmal im voraus!
Kathrin
Hi,
Jeder User hat 2 Tables:
eieiei.
Als ich mit dem Projekt begonnen habe, dachte ich noch, alle Nachrichten für alle User in einem Table speichern ist doch total doof.
Falsch. Alle Nachrichten für alle User in _mehr_ als _insgesamt_ einer Tabelle zu speichern ist doof. Gleiches gilt für alle übrigen Daten: Alle Userdaten landen in einer einzigen Tabelle, alle Kontaktdaten landen in einer einzigen Tabelle. Genauer gesagt:
Alle gleichförmigen Daten gehören immer in ein und die selbe Tabelle.
Andersherum gehören Daten, die nicht gleichförmig sind, in eine andere Tabelle. Fällt Dir also beispielsweise ein, dass ein "blockierter" User etwas anderes ist als ein Kontakt, also mehr (oder weniger - jedenfalls andere) Daten benötigt, ist Dein derzeitiges Modell fehlerhaft: Du benötigst dann eine Tabelle "kontakt" und eine Tabelle "blockierung" (zudem "bookmark" und was immer Du noch in Deiner jetzigen Tabelle unterbringst).
Jetzt denke ich allerdings, bei 1 Million User wären in dieser Datenbank 2 Millionen Tables, und das ist ja noch doofer. :-(
Richtig. Und zwei Millionen mal n Indizes[1].
Vielleicht sollte ich die User alphabetisch ordnen.
Nein.
Habt ihr Erfahrung mit sowas?
Ja. Tabellen mit diversen Milliarden Datensätzen sind keine Unbekannten.
Wie macht man sowas professionel?
Wie oben beschrieben.
Cheatah
[1] Naja, eine Million mal (n plus m).
Falsch. Alle Nachrichten für alle User in _mehr_ als _insgesamt_ einer Tabelle zu speichern ist doof. Gleiches gilt für alle übrigen Daten: Alle Userdaten landen in einer einzigen Tabelle, alle Kontaktdaten landen in einer einzigen Tabelle. Genauer gesagt:
Alle gleichförmigen Daten gehören immer in ein und die selbe Tabelle.
Aber die wird doch dann unendlich rießig!
Stell Dir mal vor Du hast 1 Million User und jeder hat 100 Nachrichten.
Die kann ich doch nicht ALLE in einem Table speichern???
Wird das dann nicht auch unendlich langsam??
Andersherum gehören Daten, die nicht gleichförmig sind, in eine andere Tabelle. Fällt Dir also beispielsweise ein, dass ein "blockierter" User etwas anderes ist als ein Kontakt, also mehr (oder weniger - jedenfalls andere) Daten benötigt, ist Dein derzeitiges Modell fehlerhaft: Du benötigst dann eine Tabelle "kontakt" und eine Tabelle "blockierung" (zudem "bookmark" und was immer Du noch in Deiner jetzigen Tabelle unterbringst).
Meinst Du gleichförmig in der Art wie sie gespeichert sind, zb als int, oder text...
oder von der Art der Verwendung?
Im Moment ist der einzige Unterschied beim speichern, die Zahl die angibt, ob der User ein Freund, oder ein Bookmark, oder blockiert ist.
hmm.... denk denk denk grübel...
Kathrin
Hi,
Aber die wird doch dann unendlich rießig!
nein, aber riesig.
Stell Dir mal vor Du hast 1 Million User und jeder hat 100 Nachrichten.
Mit dieser Vorstellung habe ich kein Problem, es ist mir schließlich schon oft genug passiert.
Die kann ich doch nicht ALLE in einem Table speichern???
In der Tat, davon kann nicht die Rede sein. Man *kann* sie nicht alle in einer Tabelle speichern, sondern *muss* es.
Wird das dann nicht auch unendlich langsam??
Vielleicht, wenn Du keine vernünftigen Indizes anlegst.
Meinst Du gleichförmig in der Art wie sie gespeichert sind, zb als int, oder text...
Die Form der Daten. Ihre Typen, ihre Zusammenstellung. Also den Aufbau eines jeden Datensatzes.
Cheatah
Hi!
Und wenn ich alle Nachrichten in einer DB speichere, wo ist dann das Limit?
Dann erscheint Dir wahrscheinlich auch eine Nachrichtenlänge von 200-500 oder sogar 1000 Zeichen gar nicht viel.
Und ich dachte immer alles sollte möglichst klein sein. :-\
Ich trau mich's gar nicht sagen, aber ich hab eine Tabelle in der stehen nur der Username und ein dazugehöriger Wert. Da kommen nur User rein, die komplette Usergruppen blockieren wollen.
Wenn niemand Usergruppen blockiert, ist sie leer. Ich dachte eigentlich, wenn ich diesen einen Wert mit zu der Liste aller User nehme, dann speichere ich immer 0 ab und verbrauche unnötig Platz.
Von der Idee hältst Du wahrscheinlich auch nicht viel, oder?? :-(
Aber das mit den Kontakten versteh ich dann immernoch nicht ganz.
Bis jetzt wird bei einem neuen Kontakt einfach eine neue Reihe in die Tabelle eingefügt.
Aber wenn alle User in einer Tabelle stehen, muß ich ja entweder den dazugehörigen Usernamen immer wieder neu mit abspeichern (in einer neuen Reihe), oder ich hab eine bestimmte Anzahl von columns, dann kann man aber auch nur eine bestimmte Anzahl an Kontakten haben.
Oder ich speichere alle Kontakte als text mit einem Komma dazwischen.
Das hört sich irgendwie alles nicht so genial an. :-(
Ich hoffe Du verstehst was ich meine, das klingt jetzt vielleicht ein bisschen kompliziert, wenn's so da steht.
Kathrin
Hi,
Und wenn ich alle Nachrichten in einer DB speichere, wo ist dann das Limit?
wie viel Speicherplatz steht denn zur Verfügung?
Dann erscheint Dir wahrscheinlich auch eine Nachrichtenlänge von 200-500 oder sogar 1000 Zeichen gar nicht viel.
In der Tat.
Und ich dachte immer alles sollte möglichst klein sein. :-\
Das ist nicht verkehrt, allerdings auch auf keinen Fall mit Priorität versehen. Es kommt nicht auf die Größe an, sondern auf die Technik.
Ich trau mich's gar nicht sagen, aber ich hab eine Tabelle in der stehen nur der Username und ein dazugehöriger Wert. Da kommen nur User rein, die komplette Usergruppen blockieren wollen.
Klingt gut, auch wenn ich den Zweck gerade nicht verstanden habe. Viele Tabellen kommen mit zwei bis drei Spalten aus. Allerdings solltest Du, wie in diesem Thread bereits gesagt wurde, auf keinen Fall den User-Namen als Referenzierung verwenden, sondern die User-ID.
Aber das mit den Kontakten versteh ich dann immernoch nicht ganz.
Bis jetzt wird bei einem neuen Kontakt einfach eine neue Reihe in die Tabelle eingefügt.
Meinst Du Zeile (also Datensatz)?
Aber wenn alle User in einer Tabelle stehen, muß ich ja entweder den dazugehörigen Usernamen immer wieder neu mit abspeichern (in einer neuen Reihe),
User-ID, wie gesagt. Das nennt sich Referenzierung. Recherchiere auch nach dem Begriff der Normalisierung in Bezug auf Datenbanken.
oder ich hab eine bestimmte Anzahl von columns, dann kann man aber auch nur eine bestimmte Anzahl an Kontakten haben.
Das Datenbank-Modell wird auf keinen Fall verändert, um neu hinzugekommenen Daten(mengen) gerecht zu werden.
Oder ich speichere alle Kontakte als text mit einem Komma dazwischen.
Gaaanz schlechte Idee. Die Inhalte einer Tabellenzelle sind atomar.
Das hört sich irgendwie alles nicht so genial an. :-(
Deine Gefühle sprechen für Dich, junge Skywalkerin :-)
Cheatah
Allerdings solltest Du, wie in diesem Thread bereits gesagt wurde, auf keinen Fall den User-Namen als Referenzierung verwenden, sondern die User-ID.
Du meinst, weil ich die ID als int speichern kann und den Usernamen nicht?
Aber das mit den Kontakten versteh ich dann immernoch nicht ganz.
Bis jetzt wird bei einem neuen Kontakt einfach eine neue Reihe in die Tabelle eingefügt.Meinst Du Zeile (also Datensatz)?
Entschuldigung, mit Reihe hab ich Zeile gemeint.
Also steht ein User der 200 Freunde hat auch 200 Mal in der Tabelle.
bzw seine User-ID. Und die Freunde werden dann auch nur als User-ID gespeichert.
Aber das führt doch auch gleichzeitig dazu, daß ich andauernd nachschauen muß wie der User heißt, der zu der ID gehört, wenn ich das richtig verstehe.
Das Datenbank-Modell wird auf keinen Fall verändert, um neu hinzugekommenen Daten(mengen) gerecht zu werden.
Verstanden!
Ey ey Captain!
Deine Gefühle sprechen für Dich, junge Skywalkerin :-)
Ich glaub ich hab schon viel gelernt!
Aber es gibt wohl noch seeeeehhhhrr viel mehr, was ich lernen muß!
Danke übrigens für Deine Hilfe! Ich dachte schon ich werde komplett ignoriert im Forum. :-)
Kathrin
Hi,
Allerdings solltest Du, wie in diesem Thread bereits gesagt wurde, auf keinen Fall den User-Namen als Referenzierung verwenden, sondern die User-ID.
Du meinst, weil ich die ID als int speichern kann und den Usernamen nicht?
auch. Ein weiterer Grund ist die absolute Bedeutungslosigkeit einer ID neben ihrer Eindeutigkeit.
Meinst Du Zeile (also Datensatz)?
Entschuldigung, mit Reihe hab ich Zeile gemeint.
Du brauchst Dich nicht zu entschuldigen :-) es muss halt nur klar sein.
Also steht ein User der 200 Freunde hat auch 200 Mal in der Tabelle.
bzw seine User-ID. Und die Freunde werden dann auch nur als User-ID gespeichert.
Exakt.
Aber das führt doch auch gleichzeitig dazu, daß ich andauernd nachschauen muß wie der User heißt, der zu der ID gehört, wenn ich das richtig verstehe.
Nur wenn Du den Namen brauchst. SQL bietet dazu verschiedene Methoden an.
Ich glaub ich hab schon viel gelernt!
Aber es gibt wohl noch seeeeehhhhrr viel mehr, was ich lernen muß!
Beides erscheint mir richtig, und ich glaube nicht, dass Du mit Letzterem große Schwierigkeiten haben wirst.
Danke übrigens für Deine Hilfe! Ich dachte schon ich werde komplett ignoriert im Forum. :-)
Oh, das passiert hier selten. Das Ignorieren meine ich, nicht das Helfen :-)
Cheatah
Hi,
auch. Ein weiterer Grund ist die absolute Bedeutungslosigkeit einer ID neben ihrer Eindeutigkeit.
Ich hab noch einen Frage zur User-ID. Kann ich die einfach mit auto_increment erstellen, oder ist es nicht gut, wenn der erste User dann die ID 1 hat?
Dafür würde es aber vielleicht Platz sparen.
Oder man könnte mit einer hohen Zahl anfangen und dann rückwärts zählen, um mögliche Angreifer zu verwirren. ;-)
Was ich übrigens bei auto_increment nie verstanden habe ist, daß die Zahlen ja immer weiter laufen. Und wenn sich zwischendrin ein User abmeldet, dann entsteht ja eine Lücke die nie mehr gefüllt wird.
Wenn sich also dauernd User an- und abmelden wird die ID-Zahl immer höher, und erreicht vielleicht irgendwann ein Limit?
Andererseits ist int unsigned ja doch ganz schön groß. :-)
Aber das führt doch auch gleichzeitig dazu, daß ich andauernd nachschauen muß wie der User heißt, der zu der ID gehört, wenn ich das richtig verstehe.
Nur wenn Du den Namen brauchst. SQL bietet dazu verschiedene Methoden an.
Was meinst Du mit verschiedene Methoden?
Ich dachte eigentlich an sowas wie:
SELECT username FROM user_table WHERE id='1';
Ist das falsch??? :-(
Und auf id kommt ein index beim erstellen.
Ungefähr so: index(id)
Oder wäre es besser wenn nur die ersten 5 Ziffern von id einen Index haben. Ich weiß nicht, ob das bei int geht. Ich meine so wie bei Usernamen (wo ich's ja ab jetzt nicht mehr brauche :-) ):
un varchar(20), index(un(10))
Da fällt mir gleich noch was ein. Bei mir heißen die einzelnen Spalten
anstatt "username" zb: "un"
oder anstatt "zeit_des_login" zb: "z"
Ist das zuviel Platz gespart, oder sowieso sinnlos, weil es gar keinen Platz verbraucht? Oder hab ich endlich mal was richtig gemacht?? *Daumen drück*
Ich glaub ich hab schon viel gelernt!
Aber es gibt wohl noch seeeeehhhhrr viel mehr, was ich lernen muß!Beides erscheint mir richtig, und ich glaube nicht, dass Du mit Letzterem große Schwierigkeiten haben wirst.
DANKE, das ist nett!
Hoffentlich hast Du Recht!
Kathrin
Hi,
Ich hab noch einen Frage zur User-ID. Kann ich die einfach mit auto_increment erstellen, oder ist es nicht gut, wenn der erste User dann die ID 1 hat?
der Wert einer ID ist grundsätzlich beliebig. Er muss ausschließlich eine Aufgabe erfüllen: eindeutig zu sein. Ob nun eine 1 drin steht, eine 42, ein "a" oder ein komplexes Objekt, ist ebenso irrelevant wie die Reihenfolge, die die Werte ergeben. Die Markierung einer Spalte als auto_increment ist genau das Mittel, das MySQL vorsieht, um die Eindeutigkeit zu gewährleisten.
Oder man könnte mit einer hohen Zahl anfangen und dann rückwärts zählen, um mögliche Angreifer zu verwirren. ;-)
Ich glaube nicht einmal, dass ein Angreifer das bemerken würde :-)
Was ich übrigens bei auto_increment nie verstanden habe ist, daß die Zahlen ja immer weiter laufen. Und wenn sich zwischendrin ein User abmeldet, dann entsteht ja eine Lücke die nie mehr gefüllt wird.
Ja. Das ist bedeutungslos.
Wenn sich also dauernd User an- und abmelden wird die ID-Zahl immer höher, und erreicht vielleicht irgendwann ein Limit?
Ja, diese Gefahr besteht.
Andererseits ist int unsigned ja doch ganz schön groß. :-)
In der Tat. Dieser User hätte ziemlich viel zu tun ;-)
Aber das führt doch auch gleichzeitig dazu, daß ich andauernd nachschauen muß wie der User heißt, der zu der ID gehört, wenn ich das richtig verstehe.
Nur wenn Du den Namen brauchst. SQL bietet dazu verschiedene Methoden an.
Was meinst Du mit verschiedene Methoden?
Ich dachte eigentlich an sowas wie:
SELECT username FROM user_table WHERE id='1';
Wenn Du präzise nur diese Information suchst, ist das richtig. Ich dachte allerdings eher an Joins und Subselects.
Ist das falsch??? :-(
Falsch ist, wenn es auch nicht unbedingt eine Fehlermeldung verursacht, einen Zahlenwert mittels Quotes künstlich in einen String umzuwandeln. Aber sonst ...
Und auf id kommt ein index beim erstellen.
Ungefähr so: index(id)
Es ist sogar ein Unique Index. Dieser wird automatisch angelegt, wenn eine Spalte als Primary Key markiert ist.
Oder wäre es besser wenn nur die ersten 5 Ziffern von id einen Index haben.
Das wäre ziemlich viel Aufwand, nur um das vermutlich effizienteste System der Datenbank ineffizient zu machen :-)
Ich weiß nicht, ob das bei int geht. Ich meine so wie bei Usernamen (wo ich's ja ab jetzt nicht mehr brauche :-) ):
un varchar(20), index(un(10))
Auch beim Username solltest Du einen Unique Index verwenden (jedoch nicht als Primary Key). Sinnvollerweise geht dieser über den gesamten Bereich, der unique sein soll - also über den kompletten Namen.
Da fällt mir gleich noch was ein. Bei mir heißen die einzelnen Spalten
anstatt "username" zb: "un"
oder anstatt "zeit_des_login" zb: "z"
Nicht gut.
Ist das zuviel Platz gespart,
Nicht, wenn Du MySQL auf einem C-64 installiert hast. Ansonsten nenne die Spalte im Zweifel ruhig "genaue_uhrzeit_zu_der_sich_der_verdammte_user_mal_wieder_eingeloggt_hat".
Oder hab ich endlich mal was richtig gemacht?? *Daumen drück*
Dein Daumendrücken hat gewirkt: Es war _nicht_ richtig. Je mehr Fehler frühzeitig entdeckt werden, umso besser für Dich :-)
Hoffentlich hast Du Recht!
Ich kann mich nicht irren. [dsf 4.14]
Cheatah ;-)
Was ich übrigens bei auto_increment nie verstanden habe ist, daß die Zahlen ja immer weiter laufen. Und wenn sich zwischendrin ein User abmeldet, dann entsteht ja eine Lücke die nie mehr gefüllt wird.
Ja. Das ist bedeutungslos.
Zur weiteren Erklärung:
Ich würde es nicht als bedeutungslos betrachten, sondern als äußerst praktisch (eben auf Grund der Eindeutigkeit).
Solltest Du nämlich irgendwo in den Untiefen Deiner Datenbank einen Datensatz haben(z.B. Foreneintrag mit einer nicht mehr vorhandenen User-ID), dann würde ja plötzlich das Statement von einem anderen User sein... Aua! :)
Samoht
Solltest Du nämlich irgendwo in den Untiefen Deiner Datenbank einen Datensatz haben(z.B. Foreneintrag mit einer nicht mehr vorhandenen User-ID), dann würde ja plötzlich das Statement von einem anderen User sein... Aua! :)
Allerdings ist es vermutlich auch ganz gut FOREIGN KEY Constraints und / oder Trigger zu verwenden, damit solche toten Datensätze gar nicht erst auftreten können :-)
cu,
Murphy
yo,
Alle Userdaten landen in einer einzigen Tabelle, alle Kontaktdaten landen in einer einzigen Tabelle.
Alle gleichförmigen Daten gehören immer in ein und die selbe Tabelle.
diese aussagen sind einfach falsch, du solltest dich mehr mit design von datenbanken auseinander setzen.
Ilja
Hi,
Alle Userdaten landen in einer einzigen Tabelle, alle Kontaktdaten landen in einer einzigen Tabelle.
Alle gleichförmigen Daten gehören immer in ein und die selbe Tabelle.
diese aussagen sind einfach falsch,
beziehst Du Dich auf Normalisierungen? Die setze ich bei obigen Behauptungen bereits voraus. Ansonsten spezifiziere bitte, was daran falsch sein soll.
Cheatah
moin,
Ansonsten spezifiziere bitte, was daran falsch sein soll.
warum sollten userdaten und kontaktdatten immer in einer tabelle sein, auch nach einer normalsierung ? was sind den gleichförmige daten ?
Ilja
Hi,
warum sollten userdaten und kontaktdatten immer in einer tabelle sein,
in _je_ einer Tabelle. Warum sollten sie nicht?
was sind den gleichförmige daten ?
Daten, die (nicht nur zufällig) den selben Aufbau und - soweit es die Datenbank betrifft - die selbe Bedeutung haben.
Cheatah
yo,
warum sollten userdaten und kontaktdatten immer in einer tabelle sein,
in _je_ einer Tabelle. Warum sollten sie nicht?
es geht nicht darum, ob sie es nicht können, es geht um deine aussage, dass es so ist. kontaktdaten könnnen durch aus in mehreren tabelle stehen, gerade nach einer normalisierung.
was sind den gleichförmige daten ?
Daten, die (nicht nur zufällig) den selben Aufbau und - soweit es die Datenbank betrifft - die selbe Bedeutung haben.
der begriff ist mir im zusammenhang mit datenbanken neu, und klingt ein wenig nach kunst. aber sicherlich sollte man ihn im kontex sehen. ich würde eher von entitäten (typen) oder auch objekten mit ihren jeweiligen attributen reden.
Ilja
Hallo.
Nicht falsch verstehen, aber Du solltest Dich zunächst mit einigen Grundlagen befassen. Z.B. hier:
http://de.wikipedia.org/wiki/Relationale_Datenbank
Grüße
Hi,
ja... gewöhne Dich an große Strukturen. MySQL ist sehr mächtig...
Und, Tipp am Rande:
Arbeite bloß nicht mit Usernamen in den Tabellen! Nur mir User-IDs...
Weil wenn ein User mal seinen Namen ändern möchte... DANN hast Du ein Problem! Sicherlich lösbar, aber zu vermeiden!
Samoht