Spalten in einer Datenbank reduzieren
lima-city → Forum → Programmiersprachen → PHP, MySQL & .htaccess
arbeiten
code
datenbank
datum
denken
index
kampf
machen
mitarbeiter
paar
problem
rede
redundanz
sekunde
spalten
stunde
tabelle
teilnehmer
unterschied
zeile
-
Ich hab da ein kleines Organisationsproblem, was eine meiner Tabellen angeht. Hintergrund ist folgendes: Ich sitze gerade an einer Kampfengine für ein Browsergame (die soweit auch auch nicht so kompliziert ist). Yedoch gibt es in diesem Spiel 7 Rassen, mit ye 7 Einheiten. Dazu noch 15 Fahrzeuge, die von allen Rassen genutzt werden können. Yetzt habe ich die Kampfengine so konzipiert, dass sie stündlich nur einen Teil des Kampfes berechnet, um Traffic und Rechenleistung zu sparen. Folglich muss ich also die Ergebnisse der einzelnen Runden zwischenspeichern, um den Kampf eine Stunde später weiterlaufen lassen zu können.
Und nun zum Problem: Zum einen brauche ich da die Daten für den Angreifer, dann für den Verteidiger und dann für die Unterstützer. Verteidiger und Unterstützer sind unterschiedlich stark, somit benötigen diese gezwungenermaßen seperate Spalten. Wir sind also bei (64*3=) 192 Spalten + ein paar Zerquetschte für Randbedingungen des Kampfes, sind wir bei etwa 200 Spalten. Das wird ne Tabelle, die ich im Leben nicht überschaut bekomme. Habt ihr eine Idee, wie ich das evtl komprimieren kann ? Oder wie andere Browsergames mit diesem Problem fertig werden ? Wäre super, wenn ihr mir da helfen könntet.
Liebe Grüße
- VampireSilence -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Es ist immer falsch zu denken, dass Datenbanken nicht dafür gedacht sind, Datenmassen zu speichern, denn genau dafür wurden Datenbanken erfunden und entwickelt. Viel wichtiger als die Masse an Daten (die durch deine Berechnungen entstehen und somit nur durch Minimierung der Rechnung minimiert werden kann) ist die Optimierung der Queries, dass diese also von der Perfomance möglichst gut sind. Wichtig hierbei ist bei rationalen Datenbanken die Relation zueinander, also lieber ein paar Tabellen mehr anlegen als nicht so rational als möglich zu arbeiten. Auch ist es falsch zu denken, dass Datenbanktabellen vom Benutzer überschaubar sein müssen, das stimmt so weit nicht, man muss lediglich wissen, wie diese aufgebaut ist und wie man mit den Daten zu arbeiten hat, aber wenn ein haufen 122,65,1,0,0,1,1,1,1 in der DB steht, dann ist das egal da man an diesen Daten nichts per Hand ändert, sondern dies per Script funktioniert. Das Problem aber über die Lesbarkeit des Users angehen zu wollen was man garnicht benötigt ist falsch. Man muss die Datenbank und die Abfragen so wohl die Scripte optimieren, bis keine Performance mehr herauszuholen ist. Dann sollte man sich überlegen, ob evtl. die Hardware zu schlecht oder der Algorithmus einfach nur zu komplex ist, was bei Spielen, bei denen man einschätzen muss ob man eine Chance hat auch nicht immer Sinn machen muss.
-
Nun ich denke, ich habe da schon einiges an Performance rausgeholt. Ich mache quasi nur eine Abfrage, hole alle Daten für den Kampf, speichere dann alles in temporären Variablen und nach dem ich den Kampf durchgerechnet habe, landen die Daten mit nur einem Schreibbefehl wieder in der DB. Es sei denn, der Kampf wird für eine Seite siegreich beendet, dann wird der Datensatz einfach komplett gelöscht und alle Teilnehmer erhalten einen Abschlussbericht. Ich bin nur mal gespannt, wie das dann tatsächlich aussieht, mit 20 Teilnehmern und 10 parallelen Kämpfen pro Stunde. Ich hoffe die DB packt das dann noch.
Liebe Grüße
- VampireSilence -
das macht 20 querys pro stunde für die kämpfe, bei denen, wie ich es verstanden habe, 10 zeilen zurückgeliefert und 10 zeilen geschrieben werden. +10 suchvorgänge, um beim SELECT den richtigen aus dem where zu finden. wenn du da auf das zu suchende attribut nen index legst, sollte bei den paar querys die DB vor lauter langweile gähnen und nach mehr arbeit betteln
PS: wie ich festgestellt habe, sind richtige DB-killer querys, in welcher 3 oder mehr tabellen gejoint werden. da geht es um ein vielfaches schneller, das in 3 querys aufzuteilen und mit where zu suchen. hab ich zwar auch gestaunt, aber was soll man machen...
Beitrag zuletzt geändert: 18.3.2009 13:38:46 von desaster-productions -
Dann scheine ich sie tatsächlich unterschätzt zu haben. o.O
Aber wie is das genau mit dem Tabellen-joinen ? Ich habe die Struktur nun nach 3. Normalform aufgebaut, in der erst nacheinander alle Teilnehmer und deren Seite ermittelt werden, und dann anhand deren Fortschrittsdaten (EXP/Forschungen/etc.) deren Stärke, sowie die Menge ihrer teilnehmenden Einheiten. Das wären damit 2 Querys, deren Result allerdings noch direkt in der selben Funktion verarbeitet werden.
Liebe Grüße
- VampireSilence -
ein join ist die verbindung mehrerer tabellen in einem query. beispiel:
SELECT mitarbeiter.ID, mitarbeiter.name, abteilung.name, mitarbeiter.gehalt, gehaltsstufe.bezeichnung FROM (mitarbeiter NATURAL JOIN abteilung) INNER JOIN gehaltsstufe ON (mitarbeiter.gehalt BETWEEN gehaltsstufe.untergrenze AND gehaltsstufe.obergrenze) WHERE irgendeine bedingung
So einen Query sollte man besser auf 2 oder noch besser auf 3 Querys aufteilen und die Join-Bedingungen einfach jeweils mit PHP-variablen in der WHERE-klausel lösen. verständlich, oder schreib ich schneller als ich denken kann? ^^
edit: noch was zu den normalformen: an sich schön und gut, aber manchmal ist es tatsächlich ratsam, redundanzen auftreten zu lassen, wenn das redundante feld nur per script beschrieben wird. vor allem, wenn sich dadurch 2 querys auf 1 query reduzieren lassen. der grund für die vermeidung von redundanzen ist die gefahr einer inkonsistenz, und die ist bei einem korrekt geschriebenen script nur durch einen Datenbankfehler möglich.
Beitrag zuletzt geändert: 18.3.2009 14:10:01 von desaster-productions -
desaster-productions schrieb:
PS: wie ich festgestellt habe, sind richtige DB-killer querys, in welcher 3 oder mehr tabellen gejoint werden. da geht es um ein vielfaches schneller, das in 3 querys aufzuteilen und mit where zu suchen. hab ich zwar auch gestaunt, aber was soll man machen...
Dem muß ich mal wiedersprechen...
In den meisten Fällen werden JOINS bzw. Subselects von Datenbanken gleich ausgeführt... kann man erkunden über "explain analyze".
Demzufolge benötigen diese auch die gleiche Zeit. Sollte dies nicht so sein, mußt du evtl. beim Join aufpassen welche Tabellen du zuerst zusammen joinst
Es macht ein Unterschied wie man zum Bsp. 3 Tabellen zusammen joint:
Tab1 und Tab2 = viele betroffene Zeilen
Tab3 = wenige Zeilen
Macht man folgendes:
Tab1 JOIN Tab2 JOIN Tab3
wird die Abfrage länger dauern
als:
Tab1 JOIN Tab3 JOIN Tab2
Generell gilt: alles was länger als 3 Sekunden dauert, muß/kann optimiert werden
Im Normalfall dauert eine Datenbankabfrage < 500 ms egal wieviele Datensätze in der Tabelle sind, wenn man den Index richtig gesetzt hat
Grüßle -
heyho! ich rede ja auch nicht von subselects, das ist ja noch immer ein einziges query. ich rede davon ein join mit 3 tabellen auf 3 normale SELECTs ohne subselect oder join aufzuteilen und mit PHP zu steuern, was in der where-klausel steht. und das ist schneller, hab ich mehrfach getestet weil ich es zuerst nicht glauben konnte.
edit: der krasseste unterschied war beim join eine scriptlaufzeit von 50 sekunden (optimiert) gegen eine mit mehreren mysql_query aufrufen mit einer laufzeit von 10 sekunden.
Beitrag zuletzt geändert: 18.3.2009 15:42:31 von desaster-productions -
Ah, ich verstehe was ihr meint. Habe aber von vornherein die Querys schon so aufgeteilt, wie ihr es vorschlagt. Da lag ich mit meiner Intuition wohl richtig.
Was die Redundanz angeht: Wenn ich eine Ebene in der Normalform nach unten gehe, benötige ich eine Kopie aller Benutzerdaten in der Kampftabelle (abgesehen mal vom Passwort, der E-Mail und den Ressourcen) und deshalb lohnt es sich wirklich nicht, da nochmal 15 Spalten pro Teilnehmer hinzuzufügen. Wenn ich Zeit habe, kann ich ya beides mal testen und dann sehen, wie lange die Querys tatsächlich brauchen. Ich denke aber, dass die Redundanz die paar ms nicht Wert sind.
Liebe Grüße
- VampireSilence
Beitrag zuletzt geändert: 18.3.2009 15:55:00 von vampiresilence -
neinneinnein, keinesfalls eine ebene runter! solche redundanzen sollen Ausnahmen zu Optimierungszwecken sein, und sind meist nur einzelne Spalten! Auf keinen Fall eine ganze Tabelle redundant in eine andere Tabelle übernehmen! Da hast du mich falsch verstanden *g*
-
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage