Rangpunkte in DB eintragen oder bei Ausgabe berechnen?
Alex
- datenbank
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:
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
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
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.
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