Spalten, Tabellen und mehr

Hallo Leute

Ich hab mal eine grundsätzliche Frage an die Leute die sich damit auskennen.

Ich sitz gerade an einer Datenbank die ziemlich viele Daten über verschiedene User abbildet.

Nun hab ich das Problem, wie bekomm ich die Daten so in die Datenbank das die Zugriffe relativ schnell bleiben. Ich muß auf fast alle Daten die dort drin sind suchen können.

Mein erstes Beispiel „alle relevanten Daten in eine Tabelle“

Heißt User, Passwort, Email, Land, Stadt, Plz, Bundesland, Beschreibungen und so weiter in eine Tabelle
Vorteil ich hab halt nur einen Select und hab sofort alle relevanten Daten zum user, email oder nach was ich gerade suche.

Mein zweites Beispiel „trenne alle Daten die updates brauchen von denen die so bleiben“
Also eine eigene Tabelle für Name, Geburtstag und eine Für die restlichen Daten.
VOrteil ist halt das man recht schnell nach dem Namen suchen kann oder nach dem Geburtstag, bzw nach den anderen Daten etwas langsamer aber dann muß man halt in der zweiten Tabelle die Restlichen Daten herraussuchen.

Mein drittes Beispiel „Trag alles in zwei Tabellen“

  1. Tabelle:
    id, user_id, name, passwort

  2. Tabelle
    id, user_id, name, value

die erste Tabelle wird jetzt gefüllt mit den usern und die zweite enthält dann die daten so

id=1
user_id=1
name=email
value=[email protected]

id=2
user_id=2
name=geburtstag
value=1.1.1970

Ja ich weiß das man dann var_char nehmen müsste für alles und das das nicht unbedingt gut ist. Aber was wäre wenn man die Tabellen dann noch einmal trennt … typ-spezifisch. Also eine Tabelle mit bool werten, eine mit int werten und so weiter.

Ich benutze MySQL. Es sind ungefähr für jeden User 100 Daten die ich speichern muß. Diese Daten sind alle zur UserID hin abhängig (für die die Normalisierung anbringen).

Ich hoffe es ist klar geworden was ich fragen will. Hab schon viel gelesen und auch schon viel gesehen und auch selber ausprobiert. Alle 3 Varianten mit 1 Mio Datensätze haben nur minimale Abweichungen in der Geschwindigkeit gebracht wobei die Tabelle wo alles in einer steht immer allein war. Allerdings waren da auch alle Spalten ausgefüllt. Heißt für jeden User 100 Daten. Wenn aber nun mal nur jeder 2. alle 100 ausfüllt und die anderen nur 10 haben wir ja schon 45% weniger daten. Bei der großen Tabelle müssten trotzdem alle Spalten in der Tabelle stehen wärend die letzte zum Beispiel nur die Daten speichern würde die auch eingegeben werden.

Naja ich danke jedem der bis hier her schon mal gelesen hat :smile:

Gruß Lamer

Moin, Lamer,

erzähl mal was über die Datenbank - 1 Million Sätze sollten einer professionellen DB keine Mühe bereiten.

Schnell geht alles, was indiziert ist (beim direkten Zugriff) und / oder im Hauptspeicher abgebildet werden kann (bei Mengenoperationen). Den Ausschlag gibt dabei nur die Menge der unterschiedlichen Schlüssel, nicht die Breite des Datensatzes. Deine 100 Felder pro Satz deuten schon mal darauf hin, dass der Entwurf nicht normalisiert ist - im Schnitt haben Tabellen selten mehr als 10 Spalten.

Gruß Ralf

Hallo,

Leider taugen alle 3 Möglichkeiten, welche du aufgelistet hast, überhaupt nicht. Wenn du mit einer (relationalen) Datenbank arbeiten willst, so sollst du sie auch so benutzen :

  • Du definierts Entitäten (User, Adresse, WasAuchImmer…)

  • Du definierst die Beziehungen zwischen deinen Entitäten

  • Du implementierst dies so
    (Das ist jetzt eine Kurzversion gewesen…)

  • 1 Mio Datensaätze sind nicht „viel“

Moin ihr beiden

Mir ist schon klar das eine Datenbank mit 1 Mio Datensätze klar kommt und das das noch nicht allzuviel ist. Hab selber Datenbanken die über 24 GB groß sind. Allerdings halten sich da halt die Spalten in maßen.

Und doch die Tabelle ist eigentlich in der 2. Normalform.

Ich speichere z.b. Daten über den User ab.

Also ungefähr so
Tabelle 1:
id (mediumint), username (varchar 30), userpasswort (varchar 32), lastlogin (int 11), firstlogin (int 11)

Tabelle 2:
Größe (smallint), Gewicht(smallint), Brille (bool), Tätoos (bool), Piercings (bool), und so weiter. Viele Bool werte die einfach das Profil des Users abbilden.
Ich glaube kaum das es sich lohnt diese Daten noch weiter zu normalisieren. Das problem ist halt ich muß auch auf jeden einzelnen Suchen können. Wenn einer eine Suche macht, ich suche jemanden für ein Kinodate dann sollen nur die leute gefunden haben die kino bool = true drin stehen haben.

Gruß Lamer

Hi Lamer,

dann hilft nur Indizieren auf Deibelkommraus.

Gruß Ralf

Hi!

Wie schon beschrieben: Es scheitert bereits am Entwurf.

Ich sitz gerade an einer Datenbank die ziemlich viele Daten
über verschiedene User abbildet.

„Viel“ ist relativ.

Heißt User, Passwort, Email, Land, Stadt, Plz, Bundesland,
Beschreibungen und so weiter in eine Tabelle

  1. Fehler: eine Tabelle
    Alleine, was Du hier aufzählst, sind bereits 4-5 Tabellen (Tabelle USER , STRASSE , LAND , BUNDESLAND , PLZ , STADT - „4-5“ deswegen, da man ev. PLZ und STADT zusammenfassen könnte, ohne allzusehr redundant zu werden.

Vorteil ich hab halt nur einen Select und hab sofort alle
relevanten Daten zum user, email oder nach was ich gerade
suche.

  1. Fehler: In einem Select kannst Du, wenn Du willst, die gesamte Datenbank abfragen (über die Performance reden wir hier noch mal nicht), nicht nur eine Tabelle.

Mein zweites Beispiel „trenne alle Daten die updates brauchen
von denen die so bleiben“

Das hast Du mit der Aufteilung beim 1. Fehler bereits gemacht: Länder, Bundesländer, PLZ, etc. bleiben gleich, lediglich die Userdaten (E-Mail, Password, Verknüpfung zu Strasse, Ort, etc.) ändern sich.

Also eine eigene Tabelle für Name, Geburtstag und eine Für die
restlichen Daten.

Ein Update betrifft IMMER die ganze Tabelle bzw. die betroffenen Sätze in der Tabelle, nie nur „ein paar Felder“.

VOrteil ist halt das man recht schnell nach dem Namen suchen
kann oder nach dem Geburtstag, bzw nach den anderen Daten
etwas langsamer aber dann muß man halt in der zweiten Tabelle
die Restlichen Daten herraussuchen.

Setze Indizes auf die Foreign-Keys und auf die am häufigsten verwendeten Suchfelder.

Mein drittes Beispiel „Trag alles in zwei Tabellen“

3.Fehler: Aber der ist bereits mit dem oben Geschriebenen behoben.

  1. Tabelle:
    id, user_id, name, passwort

  2. Tabelle
    id, user_id, name, value

So etwas schlag Dir gleich aus dem Kopf!!

id=1
user_id=1
name=email
value=[email protected]

id=2
user_id=2
name=geburtstag
value=1.1.1970

Sowas kommt oft Standardsoftware vor und wird für gewisse Anwender so umgebaut (aber auch nur im „hinteren“ Teil der Tabelle, wo man noch ein paar Felder dranfügt, die dann - je nach Kunde - verschiedene Bedeutungen haben können - aber sogar davon kommen die mir bekannten Hersteller bereits ab) - aber hier reden wir von einer gezielten Software und keiner, deren Wartung und Service allein einige 10.000e €/Jahr kostet.

Ja ich weiß das man dann var_char nehmen müsste für alles und
das das nicht unbedingt gut ist.

Das ist nicht nur gut, das ist der Tod der Software. Die ersten Probleme kommen beim Datum, die zweiten bei den numerischen Zahlen (z.B. ist der „.“ nun das Tausendertrennzeichen oder das Komma?)

Aber was wäre wenn man die
Tabellen dann noch einmal trennt … typ-spezifisch. Also eine
Tabelle mit bool werten, eine mit int werten und so weiter.

Bei meinen Softwareprojekten gab es bisher immer eine Parametertabelle, in der jeweils der Parametername, ein Char-Feld, ein Date-Feld und ein numerisches Feld vorhanden waren - aber nur einmal, um Parameter, die sich auch mal ändern können (Pfade, Steuercodes, Faktoren, etc.) zu warten - aber was Du versuchst, ist ein Datenbank-Repository nochmals abzubilden.

Diese Daten sind alle zur UserID hin
abhängig (für die die Normalisierung anbringen).

„Normalisiert“ ist in Deinen Überlegungen defintiv noch nichts.

Alle 3 Varianten mit 1 Mio Datensätze haben nur
minimale Abweichungen in der Geschwindigkeit gebracht wobei
die Tabelle wo alles in einer steht immer allein war.

Bei 1 Mio. Datensätze wirst Du zwischen einer sauberen und Deiner Lösung auch nicht viel Performance-Unterschied feststellen (drastisch ausgedrückt, aber es ist so)

Wenn aber nun mal nur jeder 2. alle 100
ausfüllt und die anderen nur 10 haben wir ja schon 45% weniger
daten.

Die „Datenmenge“ hängt weniger von den Feldern, sondern von der Anzahl der Datensätze und der „Größe“ der Felder ab - und die Datenmenge hat eigentlich nur Auswirkung auf die Speicherparameter der Tabelle.

Bei der großen Tabelle müssten trotzdem alle Spalten in
der Tabelle stehen wärend die letzte zum Beispiel nur die
Daten speichern würde die auch eingegeben werden.

Ob da nun nix oder doch etwas drinnen steht, ist irrelevant; es kommt im wesentlichen darauf an, wie die DB und die Zugriffe definiert sind.

Grüße,
Tomh

nun, für mich macht die trennung von user und userdaten keinen sinn…

ein user ist nun einmal eine person, die piercings hat, warum sollten diese daten also nicht in der selben table abgespeichert sein (das piercing gehört explizit dem user)?

was anderes ist zB ein Wohnort, bzw. ein Land, in dem der user wohnt. ein Ort hat ja mehrere Einwohner, die sonst alle die selben daten drinnen stehen hätten (name des ortes, plz, land,…)
da gäbe es dann eine eigene tabelle user (user_id, name, piercings, ort_id,…), eine tabelle ort (ort_id, name, land_id, plz,…) und eine tabelle land (land_id, name)

beispiele:

tabelle land:
land_id / name
1 / deutschland
2 / österreich
3 / schweiz
4 / italien

tabelle ort:
ort_id / name / land_id / plz
1 / Linz / 2 / 4020
2 / München / 1 / … kA welche plz münchen hat *g*
3 / Milano / 4 / dto…

und ein user schaut dann folgendermaßen aus:
user_id / name / piercings / ort_id
1 / scott / true / 1 (scott hat piercings und kommt aus linz)
2 / arnie / false / 3 (arnie hat keine piercings und kommt aus milano)
uswusf…

die selects musst du dann halt soweit anpassen, damit du die daten bekommst, die du brauchst (tabellen in from fetchen und sätze mittels where-klauseln einschränken…)

nun… wichtig ist eben die erarbeitung von entitäten (objekten) und deren beziehungen zueinander.

eben:
gaestebucheintrag (ein eintrag gehört zu einem gästebuch, ein gästebuch hat mehrere eintrage)
gaestebuch (eine person hat ein gaestebuch)
person (kommt aus einem land)
ort (ist fix einem land zugeordnet)
land

hoffe, die verwirrung ist nicht allzu groß

lg Phylanx

HI

Klar indiziert wird auch, wenn die Datenbank erstmal steht noch gibt es sie ja gar nicht. Ich mach mir ja nur Gedanken dazu und Teste.

Hi
Na für mich macht die Trennung schon Sinn (zumindest in meiner Theorie die ich mir zusammengelegt habe)

Also kleine Tabelle mit 3 Spalten für die Userdaten (id, name, passwort)
Über diese Tabelle geschieht das login und einige auswertungen laufen genau darauf. In meinem Verständniss müsste das schneller sein weil die Tabelle ja auch recht klein ist als wenn ich dort alles drin habe was ich nicht immer brauche.
Wärend die großen suchen in der/die Tabellen laufen. z.B wenn ich nach Pircings suche. Dann sucht er in der großen Tabelle das Pircing raus und hat damit alle userids die so etwas haben dann mach ich mit einem subselect/join eine abfrage auf die Userdaten und von dort einen z.B. auf die Adresse. Was zwar etwas umständlicher ist als alles in einer großen aber nicht wirklich langsamer sein dürfte mit den entsprechenden Indizies.

Und natürlich hab ich die namen der Städte, Länder und so weiter nicht in der selben Tabelle die haben alle schön eine eigene Tabelle und sind nur per Relation als int, tinyint usw in der userdatenbank vorhanden, hatte mich wohl dahingehend nicht wirklich gut ausgedrückt :smile:

Gruß Lamer

Hi
Na für mich macht die Trennung schon Sinn (zumindest in meiner
Theorie die ich mir zusammengelegt habe)

Also kleine Tabelle mit 3 Spalten für die Userdaten (id, name,
passwort)
Über diese Tabelle geschieht das login und einige auswertungen
laufen genau darauf. In meinem Verständniss müsste das
schneller sein weil die Tabelle ja auch recht klein ist als
wenn ich dort alles drin habe was ich nicht immer brauche.


:Gruß Lamer

Nein, das ist falsch :smile:. Ob deine Tabellen „Gross“ oder „Nicht Gross“ ist in Bezug auf Attribute, spielt bei den Zugriffen „überhaupt“ keine Rolle. Einzig die Datenübertragung des Resultates zum Client hängt davon ab, aber du brauchst ja jeweils nur die Attribute in deinem Select aufzunehmen, welche du auch gerade benötigst. (Mit anderen Worten, du solltest nie mit SELECT * … abfragen)

Gruss

Hi Tomh

Erstmal danke das du meine Text so auseinandergenommen hast und dich damit beschäftigt hast.

Vorneweg die Datenbank gibt es noch nicht. Bisher sind das nur Überlegungen wie ich es am besten anstelle um überhaupt richtig mit dem Entwurf anzufangen. Ich weiß noch nicht einmal genau welche Daten da hineinmüssen hab bisher nur eine ungefähre Ahnung und das es auf den User halt viele werden.

So dann antworte ich dir mal:

Klar ist viel relativ darum ja die Aussage das ich auf 80-150 Spalten kommen werde wenn ich es alles in eine Tabelle schreiben würde.

Das ist mir auch klar. Die Daten sind natürlich alle in ihrer eigenen Tabelle aber die ID von denen steht entweder in der UserTabelle oder aber es gibt noch eine RelationshipTabelle dann steht deren id dort mit drin (für 1:n Beziehungen) ich hatte das nur weggelassen da ich ja sagte das die Tabellen schon normalisiert sind und dachte ich brauch das dann nicht explizit zu sagen.

Auch das ist mir klar. Problem ist halt, genau wie du sagst die Performance. Und gerade um die geht es mir. Ich hab halt noch keine Erfahrungen mit wirklich vielen Spalten sammeln können meine größte Tabelle auf die Art und Weise waren nie mehr als 20 Spalten. Mir geht es halt nur um die Erfahrung anderer und Ratschläge.

Das ist mir auch klar darum trenn ich ja die Tabelle mit den Statischen Daten von der mit den nicht statischen. Auch wenn es mir im nachhinein nicht einfällt warum :smile:. Ich glaub wegen der Defragmentierung wenn Datensätze komplett aus der Tabelle gelöscht werden. Aber mitlerweile bin ich dazu übergegangen diese Daten nur auf delete zu setzen (eigenes feld)

Das ist natürlich auch klar. Explainanalyse und SlowQuery sei dank. Problem hierbei ist, die Tabellen gibt es noch nicht wirklich und mein Test mit den 1 Mio Datensätzen egal welches Beispiel sagt mir 0.0016-0.0020 Sekunden für eine Suche. Was für mich nicht wirklich aussagekräftig ist :smile:.

Jepp und ich wollte es halt in eine eigene Tabelle machen da ich dann das erweitern der Daten recht einfach habe. Aber wie schon gesagt hab ich das verworfen schon alleine wegen den verschiedenen Typen. Wobei ja da noch der Vorschlag ist mit den Typen Tabellen :smile:.
Damit hab ich schon mal eine größere Datenbank gemacht die auch recht schnell arbeitet. Allerdings enthält die nur 12 verschiedene Daten und nicht über 100 und somit ist das noch recht übersichtlich.

Ist das so? ich dachte immer wenn ein Select über einen Index nichts findet und dann der Such algo auch nichts ergibt das dann die ganze Tabelle durchsucht wird. Frage für mich ist sucht er dann nur die entsprechende Spalte gerade bei Komplizierteren Abfragen (wobei das kann ich mir glaub ich selber beantworten, er durchsucht nur die spalte alles andere wäre ja doof), aber um die Spalte zu finden muß er jedesmal die anderen werte durchlaufen ( ich stell mir das halt wie in einer großen csv datei vor. Nack komma 5 steht der wert … also suche komma 5 guck ob wert x = y ist wenn ja merke dir die id wenn nein … nächste zeile.

Gruß Lamer

Auch das ist mir klar. Natürlich hol ich mir über die Select abfragen nur die Daten die ich wirklich brauche.

Also bisher ist mein Consens … es ist egal wie groß die Tabelle ist und welche form ich nehme solange der Index anständig gesetzt ist geht es immer schnell. Was sich im übrigen auch mit meiner Testerfahrung deckt. 1 Mio Datensätze auf alle 3 Arten und dann eine Select suche die mir verschiedene Daten ausgibt dauerte nie länger als 0,0016-0,0020 Sekunden.

Frage ist wie das sich dann später unter Last entwickelt.

)Gruß Lamer

Hi Tomh

Auch das ist mir klar. Problem ist halt, genau wie du sagst
die Performance. Und gerade um die geht es mir. Ich hab halt
noch keine Erfahrungen mit wirklich vielen Spalten sammeln
können meine größte Tabelle auf die Art und Weise waren nie
mehr als 20 Spalten. Mir geht es halt nur um die Erfahrung
anderer und Ratschläge.

–> Falsch. Die Anzahl der Attribute ist dabei irrelevant.

Das ist mir auch klar darum trenn ich ja die Tabelle mit den
Statischen Daten von der mit den nicht statischen. Auch wenn
es mir im nachhinein nicht einfällt warum :smile:. Ich glaub wegen
der Defragmentierung wenn Datensätze komplett aus der Tabelle
gelöscht werden. Aber mitlerweile bin ich dazu übergegangen
diese Daten nur auf delete zu setzen (eigenes feld)

–> Mit fällt auch nicht ein warum :smile:. Diese Überlegung ist schlichtwegs (Verzeihung) „Unsinn“. Und das Delete - Flag macht die Sache ja noch schlimmer.

Wobei ja da noch der Vorschlag ist mit

den Typen Tabellen :smile:.
Damit hab ich schon mal eine größere Datenbank gemacht die
auch recht schnell arbeitet. Allerdings enthält die nur 12
verschiedene Daten und nicht über 100 und somit ist das noch
recht übersichtlich.

–> Das wäre dann eine Art „generisches“ Datenmodell, davon halte ich eigentlich nichts (aus verschiedenen Gründen)

Ist das so? ich dachte immer wenn ein Select über einen Index
nichts findet und dann der Such algo auch nichts ergibt das
dann die ganze Tabelle durchsucht wird. Frage für mich ist
sucht er dann nur die entsprechende Spalte gerade bei
Komplizierteren Abfragen (wobei das kann ich mir glaub ich
selber beantworten, er durchsucht nur die spalte alles andere
wäre ja doof), aber um die Spalte zu finden muß er jedesmal
die anderen werte durchlaufen ( ich stell mir das halt wie in
einer großen csv datei vor. Nack komma 5 steht der wert …
also suche komma 5 guck ob wert x = y ist wenn ja merke dir
die id wenn nein … nächste zeile.

–> Nein, Ein Index in einer RDBMS ist eben nicht wie ein grossen CSV aufgebaut. Der häufigste Typ Index ist ein B-Tree Index. Vielleicht googelst du mal am besten danach …

Gruss

Auch das kenn ich. Da brauch ich nicht googlen … aber wie der text schon sagt. Wenn er über die Indizies nichts findet was passiert dann.

Das war ja der Grund warum ich darauf gekommen bin das weniger Daten dann doch mehr Sinn machen.

-Wobei die Aussage „INDEX=Schnell“ , „Kein Index = Langsam“ so nicht richtig ist. Indexzugriffe sind gegenüber einem Scan der Tabelle immer kostspieliger. Deshalb ist dei Verwendung eines Indexes oft davon abhängig, wie gross des Resultset in Relation zur gesamten Datenmenge ist. Diese Entschiedung trifft der Optimizer für dich, abhängig von den INformationen, welche du im gibst (Statistiken…)

Gruss

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hi
ja so hab ich das auch aus dem mysql 5.1 Handbuch.

Allerdings steht da nicht wirklich genauer beschrieben ab wann das so ist.

Das wäre z.b. etwas was mich interessieren würde.

  1. Mehrere Indizies auf verschiedene Spalten.
  2. Mehrere Indizies über verschiedene Spalten
  3. Die Auswirkungen wenn die Indizies größer sind als die Tabelle (also Indizies insgesammt)

Das hab ich nämlich noch nicht gefunden.

Wobei der Indizie zwar mehr Aufwand ist für die Datenbank aber gerade durch den Indizie ja nur ein kleiner Teil der Tabelle durchsucht wird ( hab ich doch so richtig verstanden oder?)

Hi!

Zuerst: Mit Deiner Normalisierung ist der Großteils meines ersten Postings eh überflüßig geworden.

Noch ein paar Zusätzte zu Ulrichs Posting.

Klar ist viel relativ darum ja die Aussage das ich auf 80-150
Spalten kommen werde wenn ich es alles in eine Tabelle
schreiben würde.

Ich habe hier gerade vor mir eine Tabelle mit 154 Spalten und knapp 7 Mio. Datensätzen - die fetzt wie die Sau :wink:, egal, welche Attribute ich abfrage oder selektiere (siehe Ulrichs: „Indizes“)
Ob die Tabelle 20 oder 200 Attribute hat, ist relativ egal (select * ist halt ein bißchen kontraproduktiv)

Damit hab ich schon mal eine größere Datenbank gemacht die
auch recht schnell arbeitet. Allerdings enthält die nur 12
verschiedene Daten und nicht über 100 und somit ist das noch
recht übersichtlich.

Du darfst den zusätzlich Aufwand (der Implementierung und der DB) nicht vergessen: Für jede Manipulation/Selektion wird die doppelte Menge an Daten benötigt! (Der „Namens“-Satz UND der „Werte“-Satz)

Und schlußendlich verweise ich wieder auf Ulrich: B-Tree- bzw. B*-Index.

Grüße,
Tomh

Hi!

Wenn er über die Indizies nichts findet was
passiert dann.

Nichts - deshalb gibt es ja Indizes: Diese beinhalten genau das, wonach Du suchst/selektierst.

Würde es anders sein, müßte er ja auch nach dem „Finden“ im Index noch einen Full-Table-Access durchmachen, denn es könnten ja noch mehr Ergebnisse in der Tabelle vorhanden sein.

Das war ja der Grund warum ich darauf gekommen bin das weniger
Daten dann doch mehr Sinn machen.

Weniger Sätze: ja. Weniger Attribute: nein.

Grüße,
Tomh

Hi Tomh

Danke. Das war mal eine gute Aussage @ 154 Spalten und 7 Mio Datensätze. Also ist es nichts unnormales. Das war eigentlich der Hauptpunkt.

Bei dem satz bin ich etwas ins straucheln geraten, kannst du das noch mal erklären. Es ging jetzt um die Tabelle wo ich die Daten einzeln abspreichere und deren Value? oder?

Gruß Lamer

Hi!

Wobei der Indizie zwar mehr Aufwand ist für die Datenbank aber
gerade durch den Indizie ja nur ein kleiner Teil der Tabelle
durchsucht wird ( hab ich doch so richtig verstanden oder?)

Fast. In der Tabelle wird überhaupt nicht mehr „gesucht“, das hat der Index bereits gemacht. Der „gefundene“ Index verweist nur mehr auf den Satz in der Tabelle (oder mehrere).

Grüße,
Tomh