Sinnhaftigkeit meiner Datenbank



  • Moin moin! 🙂

    Ich hatte hier im Forum schonmal den Plan geäußert eine MySQL Datenbank für unsere Lan-Party turniere zu verwenden.
    Die folgende Tabellenstruktur habe ich mir überlegt und ich würde gerne wissen ob es so sinn macht, ob es optimiert werden könnte/sollte und ob es so überhaupt funktioniert.

    Was wo wie:
    - XAMPP webserver für Lanparty
    - Jeder soll die Webseite aufrüfen können die mit Php/Html geschrieben wird.
    - Ich verwalte die Datenbank.
    - Die Webseite soll rankings etc darstellen.

    Was soll alles gezeigt werden:
    - Spielerranking (Wer hat wie oft gewonnen, etc)
    - Gameranking (Wer ist in Spiel XYZ der spieler mit den meisten Gewinnen)
    - Teamranking
    beides jeweils für die eine Lan-Party oder auf alle daten der Tabelle.
    - Achievements 😃 für jeden einzelnen
    - Mehr vlt später.

    Die Tabellen die ich mir dafür überlegt habe würden so aussehen:
    (Spalten der Tabelle jeweils durch ";" getrennt)
    AchievementTable:
    Spielername; AV1; AV2; ..... (AVs jeweils 0 oder Datum)

    RoundTable:
    teamA(name); teamB(name); game; map; mode; winnerteam; date; tournamentID

    TeamList:
    TeamName; tournamentID; member1; member2;....

    Durch die Schlüssel: Spielername und TurnamentID müsste ich ja jede tabelle gut durchsucht bekommen oder?

    und nochmal eine allgemeine Frage:
    Wie groß (Zeilen und Spalten) darf eine MySQl tabelle werden?
    Lohnt es sich, lange tabellen in mehrere zu unterteilen?
    Ich denke z.b. an die Achievement Tabelle. Da könnten mit der Zeit viele Lustige Achievements drinnen landen 😃

    Gruß,
    Chris



  • cl90 schrieb:

    Die Tabellen die ich mir dafür überlegt habe würden so aussehen:
    (Spalten der Tabelle jeweils durch ";" getrennt)
    AchievementTable:
    Spielername; AV1; AV2; ..... (AVs jeweils 0 oder Datum)

    Das ist nicht normalisiert. Lieber für jedes AV ein eingener Datensatz. Also "Spielername; ldfnr; AV" oder so ähnlich. Damit bist Du nicht limitiert, wie viele AVs pro Spieler gespeichert werden.

    cl90 schrieb:

    und nochmal eine allgemeine Frage:
    Wie groß (Zeilen und Spalten) darf eine MySQl tabelle werden?

    sehr groß. Zumindest was die Anzahl der Zeilen angeht. Du wirst an keine Grenze stossen solange du weniger als ein paar Millionen Teilnehmer auf der LAN Party hast. Und bei ein paar Millionen Teilnehmer hast Du sicher ganz andere Probleme (Verkostung, Toiletten, Anfahrt, Sicherheit, usw.) 😃 .

    cl90 schrieb:

    Lohnt es sich, lange tabellen in mehrere zu unterteilen?

    Nein, auf keinen Fall. Nie und nimmer.



  • cool danke für die schnelle hilfreiche antwort.

    Also ich dachte an so eine Matrix mit den Achievements:

    name  av1      av2       av3
    xyz   0        1.1.14    0
    bla   6.8.14   0         7.8.14
    ...
    

    Dann müsste ich für jedes neue AV bloß eine neue Spalte hinzufügen und für jede person eine neue Zeile.
    Oder hättest du pro av eine Tabelle gemacht?

    Generell könnte man diese AV liste dann auch als Spielerliste allgemein benutzen.



  • tntnet schrieb:

    cl90 schrieb:

    Lohnt es sich, lange tabellen in mehrere zu unterteilen?

    Nein, auf keinen Fall. Nie und nimmer.

    Würde ich so nicht unterschreiben. Kann sich schon auszahlen. Hier natürlich nicht.

    cl90 schrieb:

    Also ich dachte an so eine Matrix mit den Achievements

    Was tntnet vmtl. meinte (und ich auch viel sinnvoller fände) wäre eher sowas:

    users(id, name, schuhgroesze)
    achievements(id, name, beschreibung)
    achievements_users(user_id, achievement_id)
    

    Damit kann jeder User jedes Achievement haben und du musst nichts am Schema ändern, wenn neue Achievements dazukommen.



  • Schon mal was von ERM und Boyce Codd Normalform gehört? Das vereinfacht die Analyse enorm, ob das Design einer DB gut ist oder nicht.



  • Ack. Die Beispiele im Wikipedia-Artikel sind ganz nett:
    http://de.wikipedia.org/wiki/Normalisierung_(Datenbank)#Negativbeispiel.3B_1NF_verletzt



  • ja gehört habe ich davon^^ meine Vorlesung zu Datenbanken ist aber schon ein bisschen her.

    ist "achievements_users(user_id, achievement_id)"
    eine Tabelle? wenn ja. Wie wird die gefüllt?
    jede userid eine zeile und dann dahinter die ganzen avids? Ist nur schlecht wegen des datums.



  • cl90 schrieb:

    ist "achievements_users(user_id, achievement_id)"
    eine Tabelle?

    Ja.

    Wie wird die gefüllt?

    Mit einer User-ID und Achievement pro Zeile.

    Wenn ich die User-ID 17 und die Achievements Nummer 42 und 48 habe, dann machst du sowas:

    insert into achievements_users(user_id, achievement_id) values(17, 42);
    insert into achievements_users(user_id, achievement_id) values(17, 48);
    

    Ist nur schlecht wegen des datums.

    Dann tu eben noch das Datum dazu in die achievements_users-Tabelle.



  • okay.

    Also sieht das dann am ende so aus:

    id    av    date
    4     15    10.1.14
    4     11    10.1.14
    7     15    11.1.14
    4     7     11.1.14
    ...
    

    Und es ist jetzt effizienter diese endlosliste nach einer user id zu durchsuchen um herrauszufinden welches av ein user hat?

    Ich würde behaupten das es einfacher ist einfach eine spalte meiner matrix zu nehmen^^
    Aber ich wette ich habe euer Vorhaben nur nicht richtig verstanden.



  • cl90 schrieb:

    Also sieht das dann am ende so aus:

    id    av    date
    4     15    10.1.14
    4     11    10.1.14
    7     15    11.1.14
    4     7     11.1.14
    ...
    

    Ja, genau.

    Und es ist jetzt effizienter diese endlosliste nach einer user id zu durchsuchen um herrauszufinden welches av ein user hat?

    Du setzt einen Index auf die User-ID und hast sofort die dazugehörigen Achievements.

    Ich würde behaupten das es einfacher ist einfach eine spalte meiner matrix zu nehmen^^

    Jedesmal, wenn ein Achievement dazukommt, musst du das DB-Schema ändern. Das ist kein gutes DB-Design. Und wenn du zusätzliche Attribute für Achievements aufnehmen möchtest, musst du das für jedes Achievement einzeln machen. Was, wenn du irgendeine Eigenschaft dieses Achievements änderst? Änderst du das für jeden User extra?

    Aber ich wette ich habe euer Vorhaben nur nicht richtig verstanden.

    Nein, du weißt einfach noch nicht viel über die Funktionsweise eines RDBMS und über DB-Design. Du hast hier eine klassische m:n-Beziehung, genau so modelliert man die.



  • hm. ne ich glaube ich hab euch auch nicht so recht erklärt was ich machen wollte.
    Denn bei meiner Matrix müsste ich die Avs gar nicht ändern.

    av1      av2     av3   .. (neue spalte für neues Av)
    pl1     0        0
    pl2     0        1.1.14
    pl3     0        0
    pl4     0        0
    

    etc..
    Funktioniert so lange wie ich nicht extra informationen hinzufügen will.

    Aber dann mach ich das jetzt mit der chaosliste. Wird dann auf jedenfall mega einfach ein formular für zu erstellen welches neue avs vergiebt.

    So aber mal zu den Spielelisten.
    Da hatte ich es ja so ähnlich geplant wie ihr jetzt mit den avs.
    Einfach untereinander weg die gespielten Spiele.

    Worüber ich jetzt noch nachdenke ist wie man die Teams verwalten kann...
    Denn die teams sind bloß sicher für ein Turnier fest. Nach jedem Turnier könnte die Teamzusammenstellung durchgemischt werden. sprich neue Teams gemacht werden.
    Das würde funktionieren, wenn vor jedem Turnierstart egal ob die Teams gleich oder anders sind, ein neuer Eintrag mit dem Team und neuer tournamentID in der team liste gemacht wird. Ist das so üblich? Einfach solche endloslisten zu machen?

    RoundTable:(untereinander die Spiele eintragen)
    teamA(name)  teamB(name)   game    map   mode   winnerteam   date    tournamentID
    
    TeamList:
    TeamName     tournamentID  member1  member2....
    


  • cl90 schrieb:

    Funktioniert so lange wie ich nicht extra informationen hinzufügen will.

    Ja, aber die Anzahl der unterschiedlichen Achievements ist ja nicht fix. Wenn du neue Achievements hinzufügst, müsstest du eine Spalte hinzufügen und dementsprechend das Schema anpassen.

    Zum Rest: Die Teamnamen verwendest du nicht direkt in der Spieltabelle. Dort verwendest du nur die Team-IDs.

    Du hast eine Tabelle mit Teamdaten, wo Team-IDs, Team-Namen und zugehörige Turnier-IDs drinstehen.

    Wieder eine Join-Table, die Spieler und Teams verbindet.

    Dann brauchst du eine Tabelle mit Turnieren.

    Eine Tabelle für gespielte Spiele.

    Und so weiter.

    Ist das so üblich? Einfach solche endloslisten zu machen?

    Ich bin mir nicht sicher, was du meinst.

    TeamList:
    TeamName     tournamentID  member1  member2....
    

    Das sieht schlecht aus. Hint: Immer dann, wenn du Attribute namens "attribut1", "attribut2", "attributn" hast, liegt eine 1:n oder m:n-Beziehung vor, die du auch richtig modellieren solltest.



  • omg 😕
    das werden ja viele Tabellen 😃
    Aber es macht schon wirklich sinn so...
    Ist nur im ersten momment seltsam da es ja auch "billiger" geht.

    Nur wie würde das dann mit den Teams aussehen?
    mal angenommen pl1 und pl4 machen ein team in turnier 7.
    und in turnier 45 machen pl1 und pl4 wieder ein Team zusammen.

    Dann trage ich in die "teamzusammenstellungstabelle" 😃 dann etwa sowas ein?:

    teamID   spieler    spieler   spieler
      1         pl1         pl4      -
     ...
     156        pl1         pl4       -
    

    Also ich soll mir ein Konzept überlegen bei dem ich niemals Spalten hinzufüge,
    sondern immer nur zeilen erweitere? Und natürlich jeweils Primärschlüssel der einzelnen Tabellen für die joints benutzen?



  • cl90 schrieb:

    das werden ja viele Tabellen 😃

    Ja, im wesentlichen eben für jede Entität eine und für jede m:n-Join-Table eine.

    Aber es macht schon wirklich sinn so...
    Ist nur im ersten momment seltsam da es ja auch "billiger" geht.

    Lies dir beizeiten mal was zu den Normalformen durch, das hilft _wirklich_ dabei zu verstehen, warum man was wie modelliert und welche Probleme man bekommen kann, wenn man es ganz anders macht.

    mal angenommen pl1 und pl4 machen ein team in turnier 7.
    und in turnier 45 machen pl1 und pl4 wieder ein Team zusammen.

    Dann trage ich in die "teamzusammenstellungstabelle" 😃 dann etwa sowas ein?:

    teamID   spieler    spieler   spieler
      1         pl1         pl4      -
     ...
     156        pl1         pl4       -
    

    Nein, nicht ganz. Auch immer nur Team zu Spieler, also eben zwei Spalten und davon für jedes Team dann drei Zeilen, weil ja jedes Team drei Spieler hat.

    Also ich soll mir ein Konzept überlegen bei dem ich niemals Spalten hinzufüge, sondern immer nur zeilen erweitere?

    Sozusagen, ja. Zusätzliche Zeilen sind neue Daten. Zusätzliche Spalten sind eine Softwareänderung.

    Und natürlich jeweils Primärschlüssel der einzelnen Tabellen für die joints benutzen?

    Joins. Aber ja. 😉



  • Mag einmal jemand die "finalen" listen abnehmen?
    für AVs Team vs. Team
    One vs. one und FreeForAll.
    Die Games bekommen jeweils keine tabelle, weil der Name die ID ist und keine weitere beschreibung nötig ist.

    Userlist:
    UserID     Username
    
    Teamlist:(TournID = TournamentID)
    TeamID     TournID       Teamname     
    
    TeamMembers:
    TeamID     UserID
    
    AvList:
    AvID       AvName       AvDescription
    
    UserAvs: 
    UserID     AvID         Date
    
    TeamBattle:(WinID = Gewinner TeamID)
    WinID      LooseID      TournID     Score    Game    Map   Mode  Date
    
    1o1Battle:(WinID = Gewinner userID)
    WinID      LooseID      Score      Game     Map     Mode  Date
    
    ffaBattle:
    ffaID      userID       Score
    

    ist es eigentlich ok die TournamentID sowohl in Teambattle liste und in Teamliste zu haben?
    Für die suche würde vermutlich viel bringen.

    Wie kann ich eigentlich die uniqe IDs generieren?



  • cl90 schrieb:

    Userlist:
    UserID     Username
    
    Teamlist:(TournID = TournamentID)
    TeamID     TournID       Teamname     
    
    TeamMembers:
    TeamID     UserID
    
    AvList:
    AvID       AvName       AvDescription
    
    UserAvs: 
    UserID     AvID         Date
    

    Das sieht soweit alles mal sehr gut aus.

    TeamBattle:(WinID = Gewinner TeamID)
    WinID      LooseID      TournID     Score    Game    Map   Mode  Date
    
    1o1Battle:(WinID = Gewinner userID)
    WinID      LooseID      Score      Game     Map     Mode  Date
    
    ffaBattle:
    ffaID      userID       Score
    

    Sieht auch soweit brauchbar aus, auch wenn ich mir überlegen würde, ob du da nicht ein bisschen Redundanz drin hast. Du könntest zB. mit Table Inheritance die Gemeinsamkeiten aller Battles in eine Basistabelle ausgliedern und für 1-on-1-Spiele Pseudo-Teams mit einem Spieler erstellen oä. Aber zumindest sind keine ganz üblen Designfehler zu erkennen.

    ist es eigentlich ok die TournamentID sowohl in Teambattle liste und in Teamliste zu haben?

    Ja, in meinen Augen schon. Ein Team konstituiert sich für genau ein Tournament, könnte dann aber ja theoretisch auch an keinen Spielen teilnehmen. Und du kannst damit sicherstellen, dass Teamnamen für jedes Tournament eindeutig sind, indem du ein Uniqueness-Constraint auf (name, tournament_id) setzt. Wenn dir das nicht so wichtig ist, nimm die Tournament-ID der Teams eben wieder raus.

    Wie kann ich eigentlich die uniqe IDs generieren?

    Darum kümmert sich dein RDBMS. Auto-Increment Integers oder Sequences oder UUIDs.



  • Ich habe mir überlegt für die Tournaments auch noch eien Tabelle zu machen.
    ALso mit ID, Name, und Datum, (n vs. n)

    Wie meinst du das mit den Pseudo Teams? Ich weiß nicht wie ich die Teambattles von den 1on1 auseinander halten soll wenn die nicht in eigenen Tabellen sind, oder ich füge meiner neuen Tournamentliste noch ein "n vs. n" feld hinzu.

    Zu den IDs nochmal. ich bin ein bisschen verwirrt, ob die IDs jetzt datenbank intern sind, oder wirklich wie ich hier andeute eine eigene Spalte haben.
    Bei manchen tabellen müsste ich pro eintrag immer eine neu ID generieren (am einfachsten wäre wohl ein laufindex) den ich dann bei selber beim hinzufügen neuer Teams, battles eintragen muss.
    Sollte eigentlich jeder Battle auch eine eigene ID bekommen?

    Ich hänge aktuell an dem Punkt wie ich eine ID in aufsteigender Folge für einen neuen Eintrag automatisch generieren lasse.



  • cl90 schrieb:

    Wie meinst du das mit den Pseudo Teams? Ich weiß nicht wie ich die Teambattles von den 1on1 auseinander halten soll wenn die nicht in eigenen Tabellen sind, oder ich füge meiner neuen Tournamentliste noch ein "n vs. n" feld hinzu.

    Schau dir das mal an:
    http://stackoverflow.com/questions/3579079/how-can-you-represent-inheritance-in-a-database

    Zu den IDs nochmal. ich bin ein bisschen verwirrt, ob die IDs jetzt datenbank intern sind, oder wirklich wie ich hier andeute eine eigene Spalte haben.

    Letzteres.

    Bei manchen tabellen müsste ich pro eintrag immer eine neu ID generieren (am einfachsten wäre wohl ein laufindex) den ich dann bei selber beim hinzufügen neuer Teams, battles eintragen muss.

    Du brauchst die ID nicht selbst erstellen; das ist der Teil um den sich dein DBMS kümmern kann. Wie genau das geht, hängt davon ab, welches DBMS du verwendest. Verwendest du MySQL? Dann such nach Autoincrement. Verwendest du Postgres? Dann such nach Sequences.

    Sollte eigentlich jeder Battle auch eine eigene ID bekommen?

    Im Normalfall finde ich es praktisch, jeder Tabelle eine ID-Spalte zu geben. Außer vielleicht reinen Join-Tables.

    Ich hänge aktuell an dem Punkt wie ich eine ID in aufsteigender Folge für einen neuen Eintrag automatisch generieren lasse.

    Siehe oben. Autoincrement oder Sequences oä.



  • ich versteh einfach nicht wieso es so "schwer" sein kann eine ID automatisch zu erhöhen...
    Ich bekomms einfach nicht hin.

    INSERT INTO userlist (userID, userName, userPass) VALUES (NULL, '$user', '$pw')
    

    ich hab auch scho einen Quatsch hier probiert:

    INSERT INTO userlist (userID, userName, userPass) VALUES ('LAST_INSERT_ID()+1', '$user', '$pw')
    

    Was soll auch z.b. ein autoincrement column sein? ich kann sowas nicht in phpmyAdmin in der mysqlDb bei den zeilen auswählen..



  • Welches RDBMS verwendest du denn? MySQL?

    Dann machst du userID zu einer Autoincrement-Integer-Spalte und fügst dann so ein:

    INSERT INTO userlist(userName, userPass) VALUES('cl90', 'secret');
    

Log in to reply