Portal > Foren > PHP > PHP-Programmierung > Problem mit zu vielen MySQL-Querys / Grundkonzeption
Antwort
 
Themen-Optionen
Alt 26.08.2006, 22:33 Nach oben    #1
Christian Mühlroth
 
Benutzerbild von Chr!s
 
Registriert seit: 04.09.2005
Ort: Nürnberg
Beiträge: 561
Standard Problem mit zu vielen MySQL-Querys / Grundkonzeption

Tag,
nun ich bin an einem Punkt, andem mein Projekt langsam an programmiertechnischer Größe gewinnt. Hierbei bin ich nun auf ein Problem gestoßen, welches von recht großer Bedeutung ist: die Performance. Dabei geht es um meine Template-Klasse und um die Sprachvariablen.

Kurze Erklärung:
Ich speichere meine Sprachvariablen (auch ganze Phrasen) in der Datenbank. Ich habe mich für die Datenbank entschieden, da ich diese Lösung dynamischer und für den Admin der Software leichter zu verwalten finde. Ich hab das so gelöst, dass ich die TemplateEngine (Methode: replaceLanguageVariables()) die Sprachvariablen per regex raussucht (gekennzeichnet mit {§sprachVariable§}), und die nötigen Felder dann aus der Datenbank holt.

Das hat am Anfang auch perfekt und schnell geklappt, hatte hier ja schonmal eine Frage dazu gestellt. Nun habe ich aber festgestellt, dass der Aufbau meiner Seiten ca. 0.1 Sekunden braucht - ist zwar immer noch schnell, für mich aber noch nicht schnell genug. Vorallem wenn das System noch wächst, und noch mehr hinzukommt. Doch dann habe ich angefanen, Templates zu verschachteln (z.b. HTML Kopf und Fuß), und auch einige Grundrahmen innerhalb der Tempaltes zu includen, damit nicht so viel an den Templates zu verändern ist, sondern einfach nur der neue COntent generiert werden muss - das ist ja auch der Sinn von Tempaltes. Doch bei jedem neu includierten Template müssen ja auch die dortigen Sprachvariablen gesucht und ersetzt werden - und so häufen sich die Querys leider nach und nach.

Dann gibt es noch das Problem, dass ich beispielsweise mal eine einzelne Sprachvariable brauch (Methode getLanguageVariable()), was dann natürlich wieder einen einzelnen Query erfordert, sodass ich zurzeit auf maximal 15 Querys / Seite komme, bei einer Laufzeit von ~0.1 - 0.13 Sekunden. Das sieht wie folgt aus:
Code:
// SessionDaten auslesen
SELECT sessionData FROM xpc1_sessions WHERE sessionID = 'd356ca7d1853009a9b51609d2da598a7' AND expireDate >= '1156623419'

// Aufgrund von session_regenerate_id() wird die alte SessionID gelöscht
DELETE FROM xpc1_sessions WHERE sessionID = 'd356ca7d1853009a9b51609d2da598a7'

// Hier werden die MainSettings geladen
SELECT c.styleID, c.chattitle, c.gzCompression, s.name, s.path, s.templatepath, s.imagepath, s.cachepath, s.csspath, s.jspath, s.fileextension, l.langname, l.langidentifier FROM xpc1_config AS c INNER JOIN xpc1_styles AS s ON s.id = c.styleID INNER JOIN xpc1_languages AS l ON l.id = c.languageID

// Auslesen der UserDaten des eingeloggten Users 
SELECT id, username, usergroup, status FROM xpc1_users WHERE id = '1'

// Query für den StatusSelector (online, abwesend, unsichtbar etc..)
SELECT id, statusIdentifier FROM xpc1_status

// Dieser Query ist für die Anzeige "Wer ist Online"
SELECT u.id AS userID, u.username, c.id AS roomID, c.roomname FROM xpc1_users AS u LEFT JOIN xpc1_chatrooms AS c ON u.chatroom = c.id WHERE u.chatroom != '0' AND u.isOnline = '1'

// Ab hier - Languagevariablen..
// Raumübersicht
SELECT phraseContent, identifier FROM xpc1_language_de WHERE identifier IN ('roomOnline')

// Raumübersicht -> keine User online
SELECT phraseContent, identifier FROM xpc1_language_de WHERE identifier IN ('noUserOnline')

// Einzelne Variablen für die Breadcumb-Navigation
SELECT phraseContent FROM xpc1_language_de WHERE identifier = 'userControlCenter'
SELECT phraseContent FROM xpc1_language_de WHERE identifier = 'manageFriendlist'
SELECT phraseContent FROM xpc1_language_de WHERE identifier = 'deleteUser'

// Verschachtelte Templates
SELECT phraseContent, identifier FROM xpc1_language_de WHERE identifier IN ('usercontrolcenterWelcometext')
SELECT phraseContent, identifier FROM xpc1_language_de WHERE identifier IN ('youAreHere','yourStatus','friendsOnlineNum','xNewPMs','oneNewPM','noNewPMs')
SELECT phraseContent, identifier FROM xpc1_language_de WHERE identifier IN ('manageFriendlistWelcome','addUser','addUser')
SELECT phraseContent, identifier FROM xpc1_language_de WHERE identifier IN ('online','busy','rightback','away','longeraway','invisible')
Indexes sind natürlich gesetzt.

Vielleicht hat von euch einer eine Idee, wie ich das System optimieren kann, sodass ich vllt weniger Querys brauche? Leider habe ich da keine passende Idee dazu gehabt, somit poste ich die Frage einfach mal hier.

Hoffe auf gute Ideen
__________________
http://www.ChrisDiary.De

Geändert von Chr!s (26.08.2006 um 22:36 Uhr).
Chr!s ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 26.08.2006, 23:47 Nach oben    #2
leftover when bar closes
 
Benutzerbild von dsxs
 
Registriert seit: 29.06.2006
Ort: Bern
Beiträge: 123
Standard

Hmm, was ich auf die Schnelle gerade sehe: die Userdaten könntest du nach erfolgreichem Login doch direkt in die Session legen. Bei deinem Sessionhandler passiert ohnehin bereits eine Querie vor und eine nach der Ausführung des Scripts ("unsichtbar"). Das ginge also gleich in einem Zug.

Wobei diese eine Querie natürlich noch keinen grossen Unterschied machen wird.
Das Problem liegt klar bei deinen Sprach-Abfragen. Wie wäre es, wenn du Spracheinträge geschickt gruppierst und die ganze Gruppe mit einer einzigen Query ausliest? (serialize(), unserialze())

Zb sämtliche Sprach"dateien" für Menüelemente wie Kopieren, Löschen, Editieren, Verschieben, Erstellen uswusw... All diese Elemente könntest du serialisieren und im Feld "usrControls" speichern... Auslesen, unserialize und du hast ein praktisches assoziatives Array mit den Daten.
Das ganze setzt natürlich ein geschicktes System voraus, die Elemente müssten logisch gruppiert werden.
__________________
Unkraut ist die Opposition der Natur gegen die Regierung der Gärtner.
ticketbörse

dsxs ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.08.2006, 01:13 Nach oben    #3
Christian Mühlroth
 
Benutzerbild von Chr!s
 
Registriert seit: 04.09.2005
Ort: Nürnberg
Beiträge: 561
Standard

Zitat:
Hmm, was ich auf die Schnelle gerade sehe: die Userdaten könntest du nach erfolgreichem Login doch direkt in die Session legen.
Das wird auch gemacht, jedoch werden die bei jedem Reload evtl aktualisiert, und müssen somit neugeladen werden (da kommen noch mehr Daten dazu).

Zitat:
Das Problem liegt klar bei deinen Sprach-Abfragen. Wie wäre es, wenn du Spracheinträge geschickt gruppierst und die ganze Gruppe mit einer einzigen Query ausliest?
Das hört sich eigentlich ganz gut an. Ich könnte eine dritte Spalte hinzufügen, und diese dann logisch Gruppieren.

Einziges Problem dabei:
Standard-Wörter wie "fortfahren" "username", "Passwort" oder "Okay" (nur Beispiele, vielleicht nicht gerate die besten) müssen dennoch geladen werden. Aber ich werde mir mal Gedanken über deinen Vorschlag machen.

Falls noch andere Ideen existieren - nur her damit

//edit Ohje, derzeit ist es sogar schneller alle Sprachvariablen zu lesen und in den kleinen internen Cache (einfach ein Array) meinem View zu packen. (Es wird immer geprüft, ob die Variable nicht schomal geholt wurde, wenn doch wird auf diesen "Cache" zugegriffen). Das ändert sich aber denke ich, wenn noch mehr Sprachvariablen dazukommen (und da kommen noch einige)..
__________________
http://www.ChrisDiary.De

Geändert von Chr!s (27.08.2006 um 01:24 Uhr).
Chr!s ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.08.2006, 02:09 Nach oben    #4
Benjamin Steininger
 
Benutzerbild von robo47
 
Registriert seit: 02.06.2005
Ort: weiher im tiefsten Odenwald
Beiträge: 1.180
Standard

eine eventuell etwas umständlicher weg wäre der templateklasse beizubringen, die übersetzungen erst wenn das letzte template erkannt ist aus der datenbank zu holen, damit beugst du auch dem vor, dass du eventuell felder doppelt abholst und sobald du mit einem query alle relevanten daten abgeholt hast, dann erst werden die templates geparst, das kombiniert mit nem templates-cache vieleicht ?

mfg
robo47
robo47 ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.08.2006, 03:17 Nach oben    #5
leftover when bar closes
 
Benutzerbild von dsxs
 
Registriert seit: 29.06.2006
Ort: Bern
Beiträge: 123
Standard

Zitat:
Einziges Problem dabei:
Standard-Wörter wie "fortfahren" "username", "Passwort" oder "Okay" (nur Beispiele, vielleicht nicht gerate die besten) müssen dennoch geladen werden. Aber ich werde mir mal Gedanken über deinen Vorschlag machen.
Das musst du mir erklären.. diese Standard-Wörter kannst du auf ebensolchem Weg gruppieren und als "Packet" auslesen.

Ansonsten klingt robo's Vorschlag sehr gut, bleibt die Schwierigkeit, ein funktionelles caching für die Templates hinzukriegen. Davon hab' ich sehr wenig Ahnung, es schien mir jedoch verdammt knifflig bei meinen wenigen rein interessehalber angestekkten Testläufen.
__________________
Unkraut ist die Opposition der Natur gegen die Regierung der Gärtner.
ticketbörse

dsxs ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.08.2006, 11:04 Nach oben    #6
Christian Mühlroth
 
Benutzerbild von Chr!s
 
Registriert seit: 04.09.2005
Ort: Nürnberg
Beiträge: 561
Standard

Zitat:
Zitat von robo47
eine eventuell etwas umständlicher weg wäre der templateklasse beizubringen, die übersetzungen erst wenn das letzte template erkannt ist aus der datenbank zu holen, damit beugst du auch dem vor, dass du eventuell felder doppelt abholst und sobald du mit einem query alle relevanten daten abgeholt hast, dann erst werden die templates geparst, das kombiniert mit nem templates-cache vieleicht ?

mfg
robo47
Hm, darüber hatee ich mir auch schnoeinmal Gedanken gemacht, eine sog. "Warteschleife" für die Sprachvariablen zu erstellen, indem ich erst alle Templates hole, sie im internen "cache" (also einfach in einem internen Array) speichere und dann die Variablen einfach ersetzen lasse.

Das müsste ich mal ausprobieren, mein erster Gedanke wäre jetzt jedoch, dass mir dann entweder mein internes Array zu groß wird oder dass das dann an meiner verschachtelung der Templates hängenbleibt - ich werde es aber mal probieren.

Zitat:
Zitat von dsxs
Das musst du mir erklären.. diese Standard-Wörter kannst du auf ebensolchem Weg gruppieren und als "Packet" auslesen.
Hm, auch wieder wahr, so hatte ich jetzt gar nicht gedacht. Das wäre auch eine Möglichkeit, ich muss dann mal testen, welche von beiden plausibler ist.
__________________
http://www.ChrisDiary.De
Chr!s ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.08.2006, 11:19 Nach oben    #7
axo
Gast
 
Beiträge: n/a
Standard

naja, ein plausibler weg, um "ripple loading" zu verhindern und trotzdem "lazy loading" zu implementieren:
* du speicherst auf jeden fall alle 'einmal geladenen' language-keys in einem array. den selben key zweimal aus der datenbank zu holen, wäre ja nicht sinnvoll.
* wenn du einen language-key nicht im 'cache' finden kannst, lädst du nicht nur den wert, sondern die ganze gruppe, die diesen wert enthält, denn du wirst wahrscheinlich bald auch einen anderen wert aus dieser gruppe benötigen.

d.h. deine statements werden:
Code:
SELECT * FROM lang WHERE packet IN (
   SELECT lang_b.packet FROM lang lang_b WHERE lang_b.lang_key IN (a, b)  
)
... kannst bei bedarf auch per JOIN machen, der subselect sieht aber schöner aus.

... du musst dann halt ganz genau schauen, dass du keine werte doppelt holst (doppelte gruppen-zugehörigkeit), und wann es passieren kann, dass du doch die komplette tabelle gezogen hast.

Geändert von axo (27.08.2006 um 11:22 Uhr).
 
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.08.2006, 12:03 Nach oben    #8
Martin Breuer
 
Benutzerbild von WarrenFaith
 
Registriert seit: 17.08.2005
Ort: Berlin
Beiträge: 1.642
Standard

Robos idee ist definitiv wert, getestet zu werden.
Ähnlich wäre es einfach, gewisse Phrasen zu Gruppieren und dann mit einem Query diese Gruppe auszulesen.
Du müsstest also nur ne Gruppentabelle erstellen und jeder "Seite" eine Gruppe zuweisen. Und dann halt Gruppenweise auslesen und speichern.
__________________
I did it my way - Senseless-Blog
WarrenFaith ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.08.2006, 12:42 Nach oben    #9
Christian Mühlroth
 
Benutzerbild von Chr!s
 
Registriert seit: 04.09.2005
Ort: Nürnberg
Beiträge: 561
Standard

Zitat:
Zitat von axo
* du speicherst auf jeden fall alle 'einmal geladenen' language-keys in einem array. den selben key zweimal aus der datenbank zu holen, wäre ja nicht sinnvoll.
Das wird schon gemacht. Die Idee mit den Gruppen ist generell nicht schlecht. Werde ich mal probieren, genauso wie robos Idee, danke schonmal.
__________________
http://www.ChrisDiary.De

Geändert von Chr!s (27.08.2006 um 12:49 Uhr).
Chr!s ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.08.2006, 12:52 Nach oben    #10
leftover when bar closes
 
Benutzerbild von dsxs
 
Registriert seit: 29.06.2006
Ort: Bern
Beiträge: 123
Standard

Lol entweder ralle ich die Posts der anderen nicht ganz oder jeder hier schlägt ein wenig dasselbe vor, ein wenig anders formuliert - wir drehen uns im Kreis...
__________________
Unkraut ist die Opposition der Natur gegen die Regierung der Gärtner.
ticketbörse

dsxs ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.08.2006, 13:28 Nach oben    #11
Christian Mühlroth
 
Benutzerbild von Chr!s
 
Registriert seit: 04.09.2005
Ort: Nürnberg
Beiträge: 561
Standard

Zitat:
Zitat von dsxs
Lol entweder ralle ich die Posts der anderen nicht ganz oder jeder hier schlägt ein wenig dasselbe vor, ein wenig anders formuliert - wir drehen uns im Kreis...
Genau so ist es
2 konkrete Vorschläge habe ich jetzt bekommen, die ich auch austesten werde:
* Templates kurz intern cachen und Sprachvariablen erst am Ende ersetzen
* Sprachvariablen logisch gruppieren und auch gruppiert auslesen

__________________
http://www.ChrisDiary.De
Chr!s ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.08.2006, 13:34 Nach oben    #12
leftover when bar closes
 
Benutzerbild von dsxs
 
Registriert seit: 29.06.2006
Ort: Bern
Beiträge: 123
Standard

3. Die Möglichkeit der Kombination beider Varianten

__________________
Unkraut ist die Opposition der Natur gegen die Regierung der Gärtner.
ticketbörse

dsxs ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.08.2006, 15:17 Nach oben    #13
Martin Breuer
 
Benutzerbild von WarrenFaith
 
Registriert seit: 17.08.2005
Ort: Berlin
Beiträge: 1.642
Standard

Mein Post ist dem von axo recht ähnlich. ich sollte demnächst gründlicher querlesen, das stimmt.
__________________
I did it my way - Senseless-Blog
WarrenFaith ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 27.08.2006, 16:59 Nach oben    #14
Christian Mühlroth
 
Benutzerbild von Chr!s
 
Registriert seit: 04.09.2005
Ort: Nürnberg
Beiträge: 561
Standard

Robos Idee war die einleuchtende für mich, so hab ich mich von 16 Querys auf 7 Querys runterschrauben können, das is denk ich doch eine ganz schöne Leistung.

Das Gruppieren von Sprachvariablen fällt mir derzeit noch etwas schwer (die logische Eintelung, das müsste ich noch etwas ausbauen), aber da ich derzeit eh nur einen Query für alle Sprachvariablen benötige, ist eine gruppierung für diesen Zweck eher unnötig. Danke
__________________
http://www.ChrisDiary.De
Chr!s ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
Problem mit meiner mysql class Stefan125 PHP-Programmierung 13 20.09.2007 22:45
[Xampp 1.6.2] Mysql kann nicht geladen werden, oder doch?! kampfgnom Tools, Server, Betriebssysteme 10 14.07.2007 13:58
MySQL 5.1 kommt in die Beta-Phase Ben Nachrichten 1 02.03.2006 14:31
Problem mit Tutorial: Login mit Sessions und MySQL Jan PHP-Programmierung 10 08.01.2006 19:58
Problem bei Verwendung von IF bei MySQL Ben Datenbanken 2 22.12.2005 16:00


Alle Zeitangaben in WEZ +2. Es ist jetzt 16:57 Uhr.


Powered by vBulletin® Version 3.7.3 (Deutsch)
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44