Alex: Rangpunkte in DB eintragen oder bei Ausgabe berechnen?

Hallo,

ich habe eine Datenbank mit etwa 100 Zeilen (Benutzer) und etwa 50 Spalten (Werte/Punkte).

id  | benutzer | punkteA | punkteB | punkteC | ...
----+----------+---------+---------+---------+-----
1   | Hans     |     100 |     123 |       0 |
2   | Klaus    |      10 |      10 |     100 |
3   | Ute      |      15 |      20 |      50 |
...

Nun würde ich gerne für jeden Wert eine bestimmte Punktzahl (Rangpunkte) vergeben. Der "klassenbeste" einer Spalte soll 1.000 Punkte erhalten. und die weiteren Kandidaten dann jeweils einen relativen Wert ihrer Punktzahl zu der Gesamtpunktzahl.

Die Formel würde so aussehen:

Benutzerwert / Maximalwert * 1000

Also in dem o.g. Beispiel hätte Hans als Klassenbester bei A und B 2.000 Punkte. Da er keine C-Punkte hat, kriegt er für C keine weiteren Punkte.

Klaus ist Klassenbester bei C und hat schonmal 1.000 Punkte. Dazu kommen noch 100 Punkte für A (10/100*1.000) und 100 Punkte für B (10/123*1.000) => 1.181 Punkte.

Ute ist überall Klassenbeste (und auch Klassenschlechteste), aber da ich nicht nach Geschlechtern trenne, muss sie sich mit (15/100+20/123+50/100)*1.000 Punkten zufrieden geben => 813 Punkte (gerundet).

Meine Frage:
Soll ich bereits beim Eintragen der Werte in die Datenbank die Rangpunkte berechnen oder lieber bei der Ausgabe die Rangpunkte live ermitteln?

Für mich erkennbarer Vorteil, wenn ich die Rangpunkte in der Datenbank halte:
Die Abfrage dürfte etwas schneller sein, da beim Eintragen berechnet wird.

Für mich erkennbare Nachteil, wenn ich die Rangpunkte in der Datenbank halte:

  • Sobald ein Datensatz (ein Benutzer) aktualisiert wird, müssten ggf. alle anderen Rangpunkte neuberechnet und eingetragen werden, zumindest dann, wenn ein neuer Maximalwert geliefert wird.
  • will ich irgendwann mal 999 statt 1.000 Punkte für den Besten geben (eher unwahrscheinlich), müsste die DB entsprechend aktualisiert werden.

Für mich irrelevant:
Die Anzahl der Datensätze verdoppelt sich nahezu.

Zu was würdet ihr raten, seht ihr weitere Vor-/Nachteile in der ein oder anderen Lösung?

Gerne nehme ich Anregungen entgegen, wie man die ein oder andere Lösung umsetzen kann. Ich hätte jetzt die "Liveberechnung" vermutlich in PHP gelöst, obwohl das ggf. ja auch schon in der Abfrage erledigt werden könnte!?

Gruß
Alex

  1. Hi,

    Hallo,

    ich habe eine Datenbank mit etwa 100 Zeilen (Benutzer) und etwa 50 Spalten (Werte/Punkte).

    id  | benutzer | punkteA | punkteB | punkteC | ...
    ----+----------+---------+---------+---------+-----
    1   | Hans     |     100 |     123 |       0 |
    2   | Klaus    |      10 |      10 |     100 |
    3   | Ute      |      15 |      20 |      50 |
    ...

    Nun würde ich gerne für jeden Wert eine bestimmte Punktzahl (Rangpunkte) vergeben. Der "klassenbeste" einer Spalte soll 1.000 Punkte erhalten. und die weiteren Kandidaten dann jeweils einen relativen Wert ihrer Punktzahl zu der Gesamtpunktzahl.

    Die Formel würde so aussehen:

    Benutzerwert / Maximalwert * 1000

    also ganz einfach ausgedrückt: Du willst alle Werte einer Spalte auf den Maximalwert der Spalte normieren.

    Soll ich bereits beim Eintragen der Werte in die Datenbank die Rangpunkte berechnen oder lieber bei der Ausgabe die Rangpunkte live ermitteln?

    Ich würde Rohwerte speichern, so wie du es bisher tust, und die Normierung bei der Abfrage machen. Den Maximalwert der Spalte findet die DB allein recht schnell.

    Falls es die Tabelle wirklich mal so umfangreich wird, dass die Maxumum-Suche beim Auslesen ein Performance-Engpass wird, könntest du einen Pseudo-User hinzufügen, der beim Eintragen die Max-Punktzahlen jeder Spalte bekommt. Das wäre ein zusätzliches UPDATE-Statement. Dann muss die Suche nach dem Max-Wert nur noch beim Eintragen erfolgen, nicht mehr beim Abfragen, aber du bleibst trotzdem flexibel und kannst das Maximum nach Belieben auf 1.0, auf 100% oder auch auf 1000 abbilden.

    So long,
     Martin

    --
    Der Professor sitzt beim Essen in der Mensa. Ein Student setzt sich ihm unaufgefordert gegenüber.
    Professor: Seit wann essen denn Schwein und Adler an demselben Tisch?
    Student:   Na gut, dann flieg' ich eben zum nächsten Tisch.
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
  2. Meine Herren!

    Die Rangpunkte werden aus den Punkte-Spalten abgeleitet. Wenn du diesen abgeleiteten Wert wiederum in der Datenbank speicherst, dann liegt diese Information also redundant vor. Das Porblem von Redundanz ist, dass man besondere Rücksicht auf die Konsistenz der Daten nehmen muss. Deshalb sollte man sie vermeiden.

    Was deine Performanz-Bedenken angeht, die schmeiß erstmal über Board. Ich halte es für höchst unwahrscheinlich, dass das zu deinem Flaschenhals werden könnte. Sowieso ist es höchst ineffektiv Leistungs-Optmierung auf Verdacht zu betreiben. Meiner Erfahrung nacht tut man besser daran, Software zunächst nur unter architektonischen Gesichtspunkten zu entwickeln. Wenn sich daraus ein Problem mit der Performanz ergibt, dann sollte man die Schwachstellen analysieren und da nachbessern, wo Bedarf besteht.

    Und falls dein Flaschenhals doch genau an dieser Stelle liegen sollte, dann würde ich keine Zeit daran verschwenden, zu versuchen die Werte auf eigene Faust zwischenzuspeichern. Ich würde dann eher auf eine bewehrte Caching-Strategie setzen, zum Beispiel den mysql-Anfragecache. Das kann dir viel Arbeit ersparen, zum Beispiel wenn es darum geht herauszufinden, wann der Cache invalidiert werden muss. Ein Problemfall hast du ja schon richtig erkannt: Wenn sich die Punkte eines Schülers ändern. Ein anderer Fall wäre zum Beispiel, wenn sich die Formel zum Berechnen der Rangpunkte ändert. Es ist sehr schwierig sich alle Problemfälle vor Augen zu führen, insbesondere auch, wenn verschiedene Entwickler am Werk sind, oder wenn die Entwicklung sich über einen längeren Zeitraum erstreckt. Besser man lässt solche Arbeit automatisert von einem Caching-Framework erledigen.

    --
    “All right, then, I'll go to hell.” – Huck Finn
    1. Om nah hoo pez nyeetz, 1UnitedPower!

      Ich würde dann eher auf eine bewehrte Caching-Strategie setzen, zum Beispiel den mysql-Anfragecache.

      So ein Cache kann ganz schön wehrhaft sein.

      SCNR

      Matthias

      --
      Der Unterschied zwischen Java und JavaScript ist größer als der zwischen Che und Cher.