WernerK: Tabelle aufteilen (fiktiv)

Hallo,
Mich würde die Meinung der Datenbank Experten interessieren.
mal angenommen wir wollten das Spiel "Stadt Land Fluss" umsetzen und die Spieldaten in einer Datenbank speichern.

Man könnte eine Tabelle "spieldaten" anlegen wie folgt:

spielid,benutzer,datum,punkte,Stadt,Land,Fluss,Pflanze,Tier,Name,Beruf
-----------------------------------------------------------------------
1,Karl,19.02.2014,25,München,Marokko,Main,Mohn,Maus,Markus,Maler
2,Werner,19.02.2014,Mühlheim,,,Mais,,Martin,

Dem Spieler Werner ist nicht so viel eingefallen, wir haben also einige leere Spalten.

Wäre es sinnvoll oder eine Möglichkeit wenn man die eigentlichen "Spielwerte" in eine zusätzliche Tabelle auslagert? Also etwa:

spielid,spielwerte
-------------------------------
2, Mühlheim
2, Mais
2, Martin

So würde man Leereinträge vermeiden. Aber man hätte halt viel mehr Zeilen.

Was meint ihr. Macht so etwas Sinn? Ich sehe bei der Aufsplittung das Problem das man nicht mehr weiss welche Zeile (Eintrag) sich zu welcher Rubrik (Stadt, Land...) gehört.

Gruss
Werner

  1. Ich sehe bei der Aufsplittung das Problem das man nicht mehr weiss welche Zeile (Eintrag) sich zu welcher Rubrik (Stadt, Land...) gehört.

    Wenn die Rubrik nicht mit dazu speichert weiß mans nicht. Wenn man es tut, weiß man es :-)

    Ich würde hier abwägen was dir wichtiger ist. Hast du so viele Einträge dass leere Werte dich stören?
    Wichtiger finde ich die Erweiterbarkeit bei der ausgelagerten Tabelle. Da kannst du in jedem Spiel eigene Rubriken bringen und musst nicht die komplette Tabelle auf etliche Spalten erweitern.

    1. Hallo,

      Ich würde hier abwägen was dir wichtiger ist. Hast du so viele Einträge dass leere Werte dich stören?

      Wie ist das eigentlich genau mit leeren Strings bei einer varchar Spalte?
      Wenn ich die Doku bei MySQL richtig verstanden habe, verbraucht ein Leerstring keinen Platz.

      Wichtiger finde ich die Erweiterbarkeit bei der ausgelagerten Tabelle. Da kannst du in jedem Spiel eigene Rubriken bringen und musst nicht die komplette Tabelle auf etliche Spalten erweitern.

      Ja das sehe ich auch als Vorteil.
      Angenommen man wollte bei dieser Struktur noch eine neue Rubrik "Farbe" hinzufügen, könnte man dies nur durch einen nachträglichen Alter Table Befehl machen.

      spielid,benutzer,datum,punkte,Stadt,Land,Fluss,Pflanze,Tier,Name,Beruf,Farbe
      -------------------------------------------------------------------------------

      Andererseits: Angenommen man hätte hier 10 Spalten die man auslagern will.
      Wenn in der Haupttabelle 100000 Einträge wären, sind in der "Spielwerte" Tabelle schon 1 Mio Einträge drin.
      Ich habe mal testweise eine solche Beispiel Tabelle aufgesplittet. Rein vom Speicherverbrauch her bzw. Plattenplatz braucht man mit zwei Tabellen etwas mehr Platz als mit einer Tabelle.

      Gruss
      Werner

      1. Tach!

        Ich würde hier abwägen was dir wichtiger ist. Hast du so viele Einträge dass leere Werte dich stören?
        Wie ist das eigentlich genau mit leeren Strings bei einer varchar Spalte? Wenn ich die Doku bei MySQL richtig verstanden habe, verbraucht ein Leerstring keinen Platz.

        Da wird nicht mehr als ein Zählbyte gespeichert werden. Im Handbuch gibt es bei den Datentypen auch eine Seite, die sich mit dem Speicherverbrauch beschäftigt.

        Wenn du aber auslagerst, um ein paar Bytes Platz zu sparen, musst du aber auch bedenken, was deine zweite Tabelle an Platzbedarf hat. Da kommen zu jeder Zeile ja noch zwei Fremdschlüssel (Typ und Verweis auf die Raterunde des Spielers) hinzu, also 4 Bytes und gegebenenfalls eine Datensatz-ID. Wenn es weniger sind (TINYINT, SMALLINT) und damit weniger Datensätze speicherbar sind ergibt das Auslagern aus Speicherplatzgründen noch weniger Sinn, weil die Gesamtmenge schon gering genug ist. Diese Verwaltungs-Werte fressen dann den Vorteil des Platzsparens vermutlich deutlich wieder auf. Zudem kommt noch der Aufwand des Joinens.

        Für das gegebene Beispiel ergibt das Vorhaben aus der Sicht mehr Nachteile als Vorteile. Das kann aber für andere Szenarien wieder ganz anders aussehen.

        Wichtiger finde ich die Erweiterbarkeit bei der ausgelagerten Tabelle. Da kannst du in jedem Spiel eigene Rubriken bringen und musst nicht die komplette Tabelle auf etliche Spalten erweitern.
        Ja das sehe ich auch als Vorteil.

        Das wäre ein schwerer wiegende Design-Entscheidung, deren Vorteile die Nachteile des Mehrbedarfs an Platz und des Joinens locker wieder gutmachen kann, wenn der Rest des Programme entsprechend flexibel ausgelegt ist. Dabei fällt aber schon bei der Erstprogrammierung vermutlich mehr Aufwand gegenüber einer Version an, die auf festgelegte Felder ausgelegt ist. Letztere lässt sich mit verhältnismäßig geringem Aufwand erweiter, wenn man zumindest einen Großteil der Funktionalität in Funktionen abstrahiert hat und nicht nur den Copy&Paste-Programmierstil angewendet hat.

        dedlfix.

        1. Hallo dedlfix,

          angenommen man würde die Tabelle aufteilen. Zu jedem Insert in der "Haupttabelle" würde es dann 10 Inserts /rows in der zusätzlichen Tabelle geben.

          spielwerteid,spielid,spielwerte,kategorie
          -------------------------------
          1,2, Mühlheim,Ort
          2,2, Mais,Pflanze
          3,2, Martin,Name
          ...

          Die Spalte "spielwerteid" wäre "auto_increment". Bei angenommenen 100 000 Inserts / Tag oben hätte man hier schon 1 000 000 Rows bzw. IDs. Im Jahr wäre die maximale ID schon bei 365 000 000.
          Mir geht es jetzt rein um den ID Wert. Die Einträge selbst würden immer wieder gelöscht. Die ID würde ja nach einigen Jahren schon anwachsen. Allerdings hätte man bei einem Bigint ja schon noch Luft oder?

          Würde man hier überhaupt eine Spalte mit "Auto_increment" benötigen. Ausser das ein Program ein Select mit "ORDER BY spielwerteid" machen könnte, sehe ich hier keine Notwendigkeit?

          Wie machen das denn eigentlich ganz große Online Unternehmen wie ebay, Amazon usw. Selbst bei einem Bigint sind doch hier bestimmt die IDs irgendwann recht schnell "aufgebraucht". Könnte man hier die betreffenden Tabellen umkopieren und einen TRUNCATE Table machen, damit sich die IDs zurücksetzen?

          Gruss
          Werner

          1. Tach!

            Mir geht es jetzt rein um den ID Wert. Die Einträge selbst würden immer wieder gelöscht. Die ID würde ja nach einigen Jahren schon anwachsen. Allerdings hätte man bei einem Bigint ja schon noch Luft oder?

            Er wird sicher nicht bei der Hälfte schlappmachen.

            Würde man hier überhaupt eine Spalte mit "Auto_increment" benötigen. Ausser das ein Program ein Select mit "ORDER BY spielwerteid" machen könnte, sehe ich hier keine Notwendigkeit?

            Wenn du ein eindeutiges Kriterium aus anderen Werten bekommst (auch zwei oder mehr zusammen), dann brauchst du keinen eigenständigen ID-Wert.

            Wie machen das denn eigentlich ganz große Online Unternehmen wie ebay, Amazon usw.

            Die spielen kein Stadt-Land-Fluss :) Mehr weiß ich auch nicht, bin kein Datenbankexperte und auch nicht mit den Problemen und Lösungsmöglichkeiten von Big Data vertraut.

            dedlfix.

  2. IMHO kann man Normalisierung pauschalisieren (Ja, bei einer n:m-Relation relativ wahrscheinlich angebracht).

    Bei Stadt-Land-Fluss würde ich nicht normalisieren, da es schier unendlich viele Kombinationsmöglichkeiten hat.

    Wenn man einer Struktur neue Eigenschaften gibt, muss generell entschieden werden, in wie fern alte Datensätze verändert werden.

    Wenn man hingegen - z.B. - irgendwelche Mitglieder irgendwelchen Teams zuorden will, würde man schon normalisieren.

    Vor allem sollte eher die Performance betrachtet werden, als die reine Datenmasse auf der Festplatte.

    MfG
    bubble

    --
    If "god" had intended us to drink beer, he would have given us stomachs. - David Daye