mmofacts.com

Performancevorteile Userquery VS Usersession

gepostet vor 18 Jahre, 9 Monate von MannaZ
Ich rufe die Userdaten (ca 100 Spalten) zurzeit bei jedem Seitenaufruf aus der Usertabelle (MyIsam) auf.

Nun hab ich mir überlegt, das ich dieses zusätzliche (ziemlich großes) Query sparen könnte indem ich die Userdaten einmal in die Session speichere und aus dieser Lade.

Soweit ich weiss werden die Sessiondaten aber auf Platte gespeichert, was natürlich nicht von Vorteil für die Performance wäre.

Meine Frage an euch:
Welches der beiden Vorschläge ist das kleinere Übel?
Welche alternativen Wege gäbe es an die Userdaten ranzukommen?
Wie handhabt ihr das Userdatenmannagement?

danke im Vorraus
gepostet vor 18 Jahre, 9 Monate von BjoernLilleike
Mein erster Vorschlag wäre, die Userdaten so zu reduzieren, dass nicht alle Daten bei jedem Seitenaufruf notwendig sind. Wofür brauchst du denn bei jeder beliebigen Seite 100 Werte, um sie darstellen zu können?

Was das andere angeht, würde ich dir einfach mal einen Benchmark mit deinen speziellen Daten durchzuführen. Also etwa beides nacheinander versuchen und jeweils die Zeiten dafür stoppen und ausgeben.
Wenn du das mit Testusern ne Zeit so laufen lässt bekommst du ein ganz gutes Gefühl dafür, welche Variante wann schneller ist.

Für meine zeitkritischen Sachen lege ich bei Serverstart einen Heap an, in den ich dann jeweils die benötigten Daten reinschreibe. Das wäre auch noch einen Versuch wert, aber bestimmt eher nicht mit 100 Werten pro User..
gepostet vor 18 Jahre, 9 Monate von neit
Habs zwar noch nie ausprobiert aber kann man evtl. die Shared Memory Funktionen von PHP nutzen um sowas in's RAM zu legen?
gepostet vor 18 Jahre, 9 Monate von Kampfhoernchen
Jedes mal alle Daten aus der Datenbank zu lesen ist sicherlich nicht die schnellste Lösung. Da wäre eine Speicherung in der PHP-Session auf jeden Fall schneller. PHP speichert die Session zwar in einer Datei, aber wenn das Betriebssystem merkt, dass eine Datei ständig aufgerufen wird, so wird diese nach Möglichkeiten im RAM schon mal vorgehalten. Bei 100 Spalten wäre also ein PHP-Session auf jeden Fall schneller.
Nach unseren Benchmarks (ausgeführt auf P4M 2,5, 512 MB RAM, 40 Gig Platte mit 4200 RPM unter WIN XP bzw AMD Athlon 64 3000+ 2048 MB Ram, mehrere Festplatten mit je 7200 rpm unter Windows SBS) kam heraus, dass die Session-Lösung schon ab ca. 15 Werten (integer und varchars) schneller war. Aber überlege dir vorher, ob du wirklich jedes mal die 100 Werte brauchst. Das ist so und so langsam.
gepostet vor 18 Jahre, 9 Monate von schokofreak
Wenn du 100 Spalten hast, machst du irgend etwas falsch.
Ansonsten: Die DB ist eigentlich meist genügend performant. Sollte dort ein Leistungsproblem auftreten dann in die Session schreiben. Wieso? Session ist immer schneller als DB.

Die Session wird als serealisiertes Objekt im FileSystem gespeichert. Das FileSystem wiederum hat je nach Server-Konfiguration einen recht grossen Software-Cache plus auch noch einen Platten-Cache. Sprich: Dort entstehen bei häufigen Reload-Intervallen keine Leistungsprobleme.

Um die Session dennoch zu Tunen würde ich zwei sachen machen:
- Kuck dass du die Daten für die Session wirklich sauber aufgearbeitet hast... sprich ich würde EIN Objekt machen, ohne irgendwelche Metadaten / Container-Funktionalität.
Die Session wird so gespeichert:

A) Möglichst eigene Partition für die Sessions verwenden (Fragmentierung). Auf dieser n relativ hohen Software-Cache einschalten. Wenn durch n Absturz die Daten nimmer geschrieben werden können, wen störts?

B) Wenn dies noch nicht genügt: Die Session-Daten in einer Ramdisk speichern. Hier ist jedoch zu beachten, dass PHP alergisch darauf reagiert, wenn keine zusätzlichen Session-Daten erstellt werden können.
=> Platz gut abschätzen, Ausrechend reservieren, Kron bereitstellen der Notfalls die Ramdisk überwacht und gezielt Files löscht.
Lieber einmal zu viel ne Expired Session als ne Warning / Error dass keine weiteren Sessions erstellt werden können

C) Genügt auch diese Leistung immer noch nicht (kann ich mir nicht vorstellen). Es gibt einen Hack, welcher die Sessions im SHM speichert (Shared Memory). Konsequenz davon: Es wird kein Blocking mehr durchgeführt. Dies führt zwingend zu Problemen und ist in meinen Augen nicht zu empfehlen. Vorallem da das Blocking der Sessions sehr praktisch für viele andere Zwecke eingesetzt werden kann.

lange rede kurzer Sinn: Zerstör diene Query mit 100 Spalten und speichere das alles in der Session. Respektive überleg dir mal grundlegend, ob du nicht etwas falsch machst. In einer Session sind meiner meinung maximal ca. 10 Spalten. Klar, ev. gibt es Relationen welche ein Caching auch wert sind, dies sind dann aber nicht mehr zwingend Session-Variablen.

Gruss
gepostet vor 18 Jahre, 9 Monate von schokofreak
Original von neit
Habs zwar noch nie ausprobiert aber kann man evtl. die Shared Memory Funktionen von PHP nutzen um sowas in's RAM zu legen?


Kann man. Ich mache jeweils fixe / bekannte UserId's und SessionIds.
Sprich: die User haben userId von 1 bis X'XXX. Beim erstellen wird immer die nächst freie gewählt.
Das selbe gilt auch für Session IDs.

Dies bewirkt, dass man interessante / einfach zugängliche Werte problemlos im SHM speichern kann. das SHM lässt sich (dank der dadurch fest vorgegebenen und nicht überschreitbaren Menge an Spielern / Sessions) problemlos in seiner Grösse Abschätzen.

nachteil des ganzen:
-schreibzugriffe auf SHM MUSS man Synchronisieren. Dies ist speziell dank dem "schrottigen PHP" ein recht grosses Problem.
- SHM bietet nicht umbegrenzt platz; ne App. die hier viel SHM braucht kann unter umständen einer anderen APP das benötigte SHM klauen -> ist mir mal passiert dass PostgreSQL nicht mehr genügend SHM zur verfügung hatte
- die PHP-SHM Extensions sind Tricky und mit vorsicht zu geniesen. 1 ist gut; zwei andere sind Schrott.

Gruss
gepostet vor 18 Jahre, 9 Monate von schokofreak
Original von BjoernLilleike

Für meine zeitkritischen Sachen lege ich bei Serverstart einen Heap an, in den ich dann jeweils die benötigten Daten reinschreibe. Das wäre auch noch einen Versuch wert, aber bestimmt eher nicht mit 100 Werten pro User..


In PHP? Nimmt mich wunder wie! Das wär was ganz interessantes...
gepostet vor 18 Jahre, 9 Monate von MannaZ
Ok, danke erstmal für eure Tips,

das mit den 100 Werten ist noch eine Altlast, die ich noch aus den Anfangszeiten des Spieles mit mir mitschleppe.
Ich werde aber versuchen diese Schritt für Schritt zu reduzieren und die Daten nur bei bedarf über Query zu laden.
gepostet vor 18 Jahre, 9 Monate von Skyrunner
Bei bestimmten Sachen wie zb. ne Gebäudeliste oder Userdetails (Sachen die sich nie oder ganz ganz selten ändern) erstelle ich zum holen der Daten eine Klasse, die die Sachen einmal aus der Db holt, die Daten in einem Rückgabeobjekt speichert und gleichzeitig dieses Objekt serialisiert und in die Session speichert. Wird die Load-Funktion der Klasse nun irgendwann später von dem User nochmal aufgerufen, dann wird nix neu aus der Db geladen sondern direkt aus der Session das Objekt unserialized.

Somit brauch ich am Aufruf der Funktion nichts ändern, das macht die Klasse ganz von selbst
gepostet vor 18 Jahre, 9 Monate von mifritscher
Hmm, mysql hat auch einen verdammt guten Cache...
Gerade wenn es viele User sind sollte mysql dank Indixes schneller sein.
gepostet vor 18 Jahre, 9 Monate von Haryl
Dazu hab ich doch glatt mal nen Benchmark, getestet wurden 20 Felder in einer Tabelle vs 20 Variablen in einer Session, beides wurde jeweils 1000 mal aufgerufen, dass sind die Ergebnisse:

mysql_query
Berechnungszeit: 0.4076 sec

Session
Berechnungszeit: 0.0116 sec


Wenn es nicht dem entspricht was du suchst, tuts mir leid ...
Und wenn jemand weitere Benchmarks braucht, ich hab mitlerweile vieeeles Gesammelt ...

mfG
gepostet vor 18 Jahre, 9 Monate von Klaus
Original von mifritscher
Hmm, mysql hat auch einen verdammt guten Cache...
Gerade wenn es viele User sind sollte mysql dank Indixes schneller sein.


Der Benchmark bestätigt aber meine Zweifel. Vergiss nicht den Verbindungsaufbau, den Overhead und die Interpreatation des SQL Befehls. Die Sessions laufen da etwas interner ab.
gepostet vor 18 Jahre, 9 Monate von mifritscher
Hmm, müsste da mal genauer forschen...
Den Verbindungsoverhead könnte man mit persistnete Verbindungen ungehen, was ich auch mache. Wie reagieren beide Systeme bei vielen (>2000) Zeilen/Datensätze, wo ich nur einen brauche? Wie bei allgemein hoher Last? Was passiert bei memory-Tabellen? Fragen über Fragen...

Den Benchmark hab ich irgendwie übersehen, weil es der erste Beitrag auf der 2. Seite war...
gepostet vor 18 Jahre, 9 Monate von KoMtuR
Original von Haryl
Dazu hab ich doch glatt mal nen Benchmark, getestet wurden 20 Felder in einer Tabelle vs 20 Variablen in einer Session, beides wurde jeweils 1000 mal aufgerufen, dass sind die Ergebnisse:

mysql_query
Berechnungszeit: 0.4076 sec

Session
Berechnungszeit: 0.0116 sec


Wenn es nicht dem entspricht was du suchst, tuts mir leid ...
Und wenn jemand weitere Benchmarks braucht, ich hab mitlerweile vieeeles Gesammelt ...

mfG


Haste auch mal versucht neben deinem 1000 mal aufrufen auch nebenbei mehrere Threads zu machen? sonst bringt das eigentlich rein garnichts, weil die Festplatte dann kaum arbeitet
gepostet vor 18 Jahre, 9 Monate von Haryl
@Klaus:
Den Verbindungsaufbau habe ich nichtmal immer neu Aufgerufen! Es war der Pure Query und aus Auswerten und anschließend in Variable schreiben...

@KoMtuR:
Nein... der Benchmark ist nun auch schon was älter (Allerdings noch in PHP5 Zeiten).
Es ging mir auch nicht darum zu Testen was bei voller Auslastung am schnellsten arbeitet, denn bei Voller Auslastung sollte man sowieso einen zweiten Server kaufen. Es bringt ja nichts alles soo knapp Auszulegen, dass es gerade so eben laufen müsste, zu Stosszeiten Klappt es dann doch nicht ...


Und ich persöhnlich benutze die Session nur für Feste Daten, wie Username, Passwort (md5), User ID usw. Allerdings nicht für Daten wie verschiedene Ressourcen und sowas, ich hab dazu zwar keinen Benchmark, aber ich denke da ist der Query schon angebrachter als das ständige neu schreiben in die Session Datei... Gerade bei mehreren Threads gleichzeitig.

Auf diese Diskussion antworten