donneo Geschrieben 3. Mai 2007 Geschrieben 3. Mai 2007 Hallo! Ich benutze bestimmt seit zwei Jahren eine Datenbankklasse, die die mysql-Funktionen von PHP kapselt. Bisher habe ich immer so gearbeitet, dass pro Seitenaufruf eine Instanz der Klasse erzeugt wird, dann die Verbindung zur DB hergestellt wird, Datenbankabfragen durchgeführt werden und dann die Seite angezeigt wird. Meinem Verständnis nach ist das ziemlich verschwenderisch. Deswegen wollte ich das Objekt in einer Sessionvariablen speichern und wiederverwenden. Das funktioniert leider nicht, und ich denke, ich habe das Problem auch schon identifiziert. Laut PHP-Doku können: ...Einige Datentypen können nicht serialisiert werden, um in Sessions gespeichert zu werden. Dazu gehören resource-Variablen oder Objekte mit Ringreferenzen (d.h. Objekte, die eine Referenz auf sich selbst an andere Objekte übergeben). ... Mit Resourcen hat man es bei den Datenbankfunktionen ja zwangsläufig zu tun, meine Idee scheint also nicht umsetzbar zu sein. Meine Frage ist nun: Kennt ihr eine andere Möglichkeit, effizienter mit der Datenbankverbindung umzugehen, oder macht ihr das alle so (ähnlich) wie ich? Viele Grüße Reinhard Zitieren
Aiun Geschrieben 3. Mai 2007 Geschrieben 3. Mai 2007 php ist (leider) instanzabhängig. Es gibt zwar Opcache-Erweiterungen aber das sind auch nur Behelfslösungen. Meineswissens gibt es keine andere Möglichkeit. Mit Templates und anderen Ressourcen ist es ja das gleiche. ...ein grund warum ich mir verstärkt Java ansehe. Zitieren
geloescht_JesterDay Geschrieben 4. Mai 2007 Geschrieben 4. Mai 2007 Der Grund, warum du das mit PHP nicht kannst oder machst, ist die Statuslosigkeit von HTTP. Eine Anfrage per HTTP kommt, wird vom Server verarbeitet, eine Antwort wird erzeugt und ausgegeben und das wars. Verbindung Client zu Server ist weg. Punkt aus, nix, niete. Jede weitere Anfrage vom selben Client ist wieder wie wenn er zuvor nie eine an den Server gestellt hätte. Als Workaround wurden ja die Sessions eingeführt (bei PHP) und die Cookies auf der Clientseite. Aber dennoch ist das nur ein Workaround. Wenn die Antwort geschickt wurde weißt du nicht, ob der Client noch da ist oder ob er sich jemals wieder meldet, ob er keine Cookies akzeptiert etc. Würdest du eine DB-Ressource jeweils für 3 Minuten offen halten (ist doch AFAIK die Standard-Sessionlebenszeit) hättest du schnell das Problem, was viele Leute mit ihren Routern bei P2P Programmen haben. Ne Menge offene Verbindungen und dann geht nix mehr. Somit hättest du ein Schild DoS zu mir! an deinen Server gehängt. Klar dauert der Verbindungsaufbau jedesmal eine gewisse Zeit (die aber, wenn es nicht sehr sehr viele Zugriffe eher vernachlässigbar ist), aber das komplett offen zu halten bringt wie gesagt ein anderes Problem. Und wenn du jetzt antwortest, dass du gar nciht so viele Verbindungen hast um damit ein Problem zu bekommen, dann frag ich dich: Wieso macht dann der Verbindungsaufbau Probleme? Außerdem hab ich irgendwo auch mal gelesen, dass der MySQL Server (andere ebenso) sich sowas merken würde und wenn vom selben Client (also PHP in dem Fall jetzt, sprich der localhost) wiederholt Verbindungsanfragen kommen wird das zwischengespeichert (Connection-Pooling) und ist somit schneller als eine komplett neue Verbindung. Und ja, das machen alle genauso. Eine Verbindung pro Skript. P.S. Java benutzt auch nichts anderes als Connection-Pooling. Oder unsere .net-Anwendungen hier. Da wird keiner eine Verbindung komplett offen halten. Und wer das doch macht, der handelt eher schlecht. Es gibt nun mal eine Obergrenze für die Anzahl offener Verbindungen. Und wenn man anfängt dafür (eine größere anzahl Verbindungen) neue Hardware anzuschaffen, könnte man das umgekehrt (Verbindungsaufbau) ja auch tun Zitieren
donneo Geschrieben 4. Mai 2007 Autor Geschrieben 4. Mai 2007 Vielen Dank für die Antwort, das klingt sinnig! Zitieren
Aiun Geschrieben 4. Mai 2007 Geschrieben 4. Mai 2007 unabhängig davon kann PHP aber generell keine Daten sessionübergreifend speichern. Was dazu führt das bestimmte Berechungen bei jedem Aufruf stattfinden müssen, Dateien und Datenbankabfragen wieder und wieder ausgeführt werden müssen. Je flexibler die Seite wird (Konfiguration, Datenabstraktionsschicht unsw) desto mehr wird jedes mal geladen, obwohl sich die sachen nur selten ändern. ich hänge das einfach mal an das Thema an vielleicht kann mich ja jemand korrigieren oder hat eine Lösung Zitieren
Eupinkepank Geschrieben 4. Mai 2007 Geschrieben 4. Mai 2007 Generell empfinde ich das aber als Vorteil von PHP. Denn aus diesem Grund kann auch auf einer relativ kleinen Maschine, relativ großes passieren. Seitenaufruf kommt. Speicher wird von php automatisch zugewiesen bzw. genutzt. Seite komplett geladen. Speicher wird automatisch geflushed. Gerade wenn Datenbankanfragen immer und immer wieder ausgeführt werden müssen, halte ich das nicht für weiter schlimm... Wer sich hier mit den Cache Funktionen von MySQL auseinandersetzt und sich eingehend mit den "Tuningmöglichkeiten" beschäftigt, wird schnell merken, dass MySQL in der "Standardinstallation" lediglich 40 bis 50% leistet (auch wenn man das sicherlich nicht in Prozenten sagen kann ) Gerade wenn ein Projekt sehr datenbanklastig ist und sich viele User auf einem System tummeln, kann ich (aus eigener Erfahrung) nur Empfehlen die OOP im Bezug auf MySQL wegzulassen (Speziell die DB Klasse in PEAR). Das ist zwar alles sehr schön und simpel, kostet aber bestimmt 20 bis 30% mehr an Resourcen in PHP. Die spar ich mir lieber auf und belaste ggf. MySQL etwas mehr. Hat man dann eine gute Datenbankstruktur, mit richtig gesetzten Indizes und gut durchdachten Abfragen, wird aus einem 75PS Golf ganz schnell ein Golf GTI. Das Problem in fast allen DB basierenden Projekten sind immer schlechte DB Strukturen, falsche bzw. fehlende Indizes, oder halt merkwürdige Abfragen. Mal ein Bespiel... Wir betreuen einen Online Shop der rund 2.800.000 Artikel in seinen DBs hat. (Musik, Buch, Film, Spiele usw). Eine Volltextsuche hat dort z.T. bis zu 5 Sekunden gedauert (ohne MySQL Cache). Wir haben da nun etwas dran rumgetuned und nun dauern die Volltextsuchen nie länger als 0.020 Sekunden (Ebenfalls ohne Cache). Alle Dinge die PHP bietet sind sicherlich toll... Aber man sollte nie die Basics (in diesem Fall MySQL) vernachlässigen. Im Bezug auf MySQL heißt das: Abfragen immer wieder testen, testen, testen... Nicht selten habe ich erlebt, dass eine simple Abfrage wie z.B.: SELECT irgendwas FROM tabelle WHERE bedingung1 AND bedingung2 deutlich langsamer lief als: SELECT irgendwas FROM tabelle WHERE bedingung2 AND bedingung1 Zitieren
geloescht_JesterDay Geschrieben 4. Mai 2007 Geschrieben 4. Mai 2007 ...oder hat eine Lösung Typo3 nutzt dafür den FE-Cache (einmal erzeugte Seiten werden gecacht und müssen nicht nochmal neu erzeugt werden, außer sie haben sich geändert. Oder du speicherst deine (aufwendigen) Berechnungen in einer Datenbank, oder legst sie sonst wo auf dem Server ab... Möglichkeiten gibt es ein paar, aber ob das unbedingt schneller ist (Zugriff auf eine Textdatei ist z.B. viel langsamer als ein DB-Zugriff) musst du dir für deine aufgaben selbst überlegen... Zitieren
Aiun Geschrieben 4. Mai 2007 Geschrieben 4. Mai 2007 naja, die OOP mal eben weglassen ist schlecht wenn es flexibel bleiben muss weil sich 'irgendwas' häufiger ändert / die Anwendung erweitert wird. Gleichzeitig kann ich dem Kunden ja nicht erzählen er muss bezahlen, ohne das klar ist ob und wieviel dabei herauskommt. Also ist auch mit tagelangem Performancetest nicht viel. Wenn ich eine Datenabstraktionsschicht als XML habe, die nur 1x beim Serverstart einlesen muss und dann auf gecached definitionen zugreife, spare ich evtl. über 100 PHP-Klassendefinitionen. Template-Files die im Cache verbleiben müssen nicht neu geparsed werden, solange sie nicht verändert werden, aber die möglichkeit sie zu verändern bleibt. Ich habe auch beispiele in denen Abfragen mehrere sekunden dauern, obwohl der Mysql-Server max. 30% der Prozessorlast belegt. Wenn ihr das Problem kennt, ich bin für Ideen und Weisheiten offen, ansonsten wäre es nicht schlecht, während die Datenbank arbeitet noch andere Prozesse laufen zu lassen (multithread) die andere Aufgaben erledigen. anderes Beispiel: der Kunde schleppt eine Zahl mit sich durch die Anwendung, die Zahl, z.B. Warenkorbgröße / verfügbarer Betrag, ist an ihn gebunden, muss aber gleichzeitig immer aktuell sein. in der Praxis heist das: Veränderungen in die Datenbank und dann summe aus der Datenbank ziehen. mit einem flexiblen Cache kann ich den Wert vorhalten und Änderungen in den Cache schieben, während der Datenbank nur die Änderungen mitgeteilt werden,sie aber nicht immer den aktuellen Wert berechnen muss. Eigentlich bevorzuge ich PHP, aber in solchen fällen sehe ich doch klare Nachteile. Zitieren
Eupinkepank Geschrieben 4. Mai 2007 Geschrieben 4. Mai 2007 Ich habe auch beispiele in denen Abfragen mehrere sekunden dauern, obwohl der Mysql-Server max. 30% der Prozessorlast belegt. Wenn ihr das Problem kennt, ich bin für Ideen und Weisheiten offen, ansonsten wäre es nicht schlecht, während die Datenbank arbeitet noch andere Prozesse laufen zu lassen (multithread) die andere Aufgaben erledigen. Das ist das Phänomen von dem ich gesprochen habe. Nehmen wir ein simples Beispiel... Eine Tabelle mit 1.000.000 Einträgen. Primärindex ist auf das Feld "id" gesetzt. Nun machst Du eine simple Abfrage: SELECT COUNT(id) AS anzahl FROM tabelle Diese Abfrage wird recht lange dauern und Du wirst sie auch nicht schneller hinbekommen... (Was will man da auch noch verändern) Schaust Du Dir während der Abfrage die Last an, so wirst Du fesstellen, dass da keine bzw. kaum Last ist. Ist ja auch logisch! Das Zählen von Datensätzen OHNE Bedingung ist ein Kinderspiel für MySQL... Dauern tut es aber dennoch. Mit einigen Tricks könnte man diese Abfrage in "NULL" Zeit durchführen lassen indem man sicherstellt, dass MySQL diesen Wert "kennt" ohne die eigentliche DB zu fragen. Also speziell in Deinem Fall: Schau Dir an, was mit MySQL (speziell MySQL 5.X) alles geht... Und da geht eine Menge. Evtl. etwas Geld in Literatur investieren. Zitieren
geloescht_JesterDay Geschrieben 4. Mai 2007 Geschrieben 4. Mai 2007 Eigentlich bevorzuge ich PHP, aber in solchen fällen sehe ich doch klare Nachteile. Dieselben Probleme wirst du aber mit JSP, ASP, Python oder was auch immer genauso haben. HTTP ist eben stateless. Mit Java (als Applet) selbst hast du das nicht, aber das liegt daran, dass du Funktionalität auf den Client verlagerst, also ein richtiges Client/Server-Programm hast. Damit hast du aber auch wieder genug andere Probleme. Eine Eierlegende-Wollmilchsau gibt es eben nicht. Ohne dein Programm jetzt genau zu kennen: Wie wäre denn eine AJAX-Lösung? Die Anzahl wird hochgezählt und im Hintergrund die Daten an den Server übermittelt. Wie gesagt kenn ich mich bei dir nicht aus, nur mal so als Schlagwort. (Ja ich weiß, mit AJAX gibt es genug andere Probleme dann ) Ich habe auch beispiele in denen Abfragen mehrere sekunden dauern, obwohl der Mysql-Server max. 30% der Prozessorlast belegt. Die Keys entsprechend setzen, deine Abfragen auf die Keys anpassen (Explain zeigt dir z.B. welche Keys genutzt werden können und welche genutzt wurden). Views für die Abfragen anlegen (erst ab MySQL 5). Allgemein gesagt gibt es da ein paar Möglichkeiten, so allgemein kann man aber nichts dazu sagen EDIT2: Auch wenn es hier ja eigentlich OT ist: MySQL AB :: MySQL 5.1 Referenzhandbuch :: 7.2 SELECT-Anweisungen und andere Anfragen optimieren Zitieren
Aiun Geschrieben 4. Mai 2007 Geschrieben 4. Mai 2007 hmm, @jester ich glaube du verstehst mich falsch ^^ Es geht nicht unbedingt um Userabhängige Daten, sondern auch um Userübergreifende. das Stateless ist da nicht so wichtig. Ich kann auch in einem Tomcat Ressourcen sessionübergreifend laden. Natürlich muss hier sichergestellt sein, das die Daten nicht verloren gehen - aber so detailiert müssen wir den teil nicht behandeln ^^ @Eupinkepank ich hatte jetzt erst befürchtet das es irgendwas ganz dummes ist, wenn die so lange brauchen ^^ aber danke, dann weis ich zumindest was ich mir ansehen kann. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.