Artikel - Detailansicht

Icon Aktuelles Performancesteigerung durch Application-Variablen

Bei CF-Applikationen mit starken Datenbankzugriff ist dieser Zugriff oft ein Engpass, der die Geschwindigkeit der Applikation bremst.
Um so wichtiger ist es deshalb, hier nach neuen Wegen der Optimierung zu suchen.

Eine Möglichkeit der Performancsteigerung ist die Zwischenspeicherung von Datenbankabfragen in Application-Variablen.

Angenommen, man hat eine Seite in einem Shopsystem, die bei jedem Aufruf eine bestimmte Liste mit Artikeln aus der Datenbank holt. Diese Liste wird monatlich in der Datenbank erneuert, so daß man davon ausgehen kann, dass sich die Daten normalerweise nicht ändern. Man müste in der Anzeige-Seite einen Code wie diesen benutzen:

<cfquery name="artikel" datasource="die_datenbank">
  select titel,preis,anzahl, bestellnr from artikel
</cfquery>

Diese Abfrage würde also beim Aufruf jeder Seite an die Datenbank geschickt. Auch wenn die Datenbank die Abfrage meistens aus dem eigenen Cache nimmt, so braucht doch die ganze Kommunikation und der Transport der Daten über das LAN seine Zeit. Ist die Datenbank dann noch zusätzlich durch anderen Clients stark belastet ist, kann dies zur merklichen Verlangsamungen kommen.
Anstatt nun diese Abfrage bei jedem Seitenaufruf erneut zu stellen, kann man die Abfrage aber auch nur einmal ausführen und das Ergebnis in einer Application-Variable speichern und bei Bedarf von dort nehmen.

Das sieht dann so aus:

<---Abfrage--->
<cfquery name="artikel" datasource="die_datenbank">
  select titel,preis,anzahl, bestellnr from artikel
</cfquery>
<---speichern--->
<cfset Application.ArtikelCache=Artikel>

Man kann dann z. B. so auf die einzelnen Spalten zugreifen:

<cfset Art=Application.ArtikelCache.titel>
<cfset Preis=Application.ArtikelCache.preis>

Natürlich kann such das ganze Recordset in eine neue Variable kopieret und dann diese weiterbenutzen werden:

<---artikel wird recordset zugewiesen--->
<cfset artikel=Application.ArtikelCache
<cfset Art=artikel.titel>
<cfset Preis=artikel.preis>

Ein Vergleich mit 100 Durchläufen in einer Schleife (Abfrage im Vergleich zu Recordset aus Application-Variable) brachte ein Ergebnis von 7 Sekunden (Datenbank) zu 10ms (Application-Variable).

Jetzt stellt sich nur noch die Frage, mit welchem Mechanismus füllt man am besten die Application-Variable und wann muß man die Abfrage direkt an die Datenbank richten. Denn irgendwann ändern sich auch mal die Daten in der Datenbank und nach einem Systemneustart sind Application-Variablen auch nicht mehr vorhanden und müssen neu angelegt werden.

Eine Variante ist der Weg über das Application.cfm-File.

Man prüft ein Flag, welches den Status der Application-Variable anzeigt. Ist diese leer, wird ein Datenbankzugriff ausgeführt und das Flag gesetzt, ist es gesetzt, wird dieser Code übersprungen. Da das Application.cfm-Template vor jedem Zugriff auf ein cfm-File ausgeführt wird, kann man dann in der Anzeige-Seite davon ausgehen, dass die Application-Variable mit dem richtigen Recordset gefüllt und benutzbar ist.

Bootet jetzt der Server irgendwann neu (gewollt oder unerwartet :-) ), ist das Flag beim Start logischerweise gelöscht und die Abfrage wird erneut gestartet. Die Application-Variable enthält somit wieder das richtige Ergebnis, bevor die Anzeigen-Seite aufgerufen wird.

Hier der komplette Code aus Application.cfm:

<---beim Start des Server ist Application.init nicht
vorhanden, also defaultmaessig Flag loeschen--->
<cfparam name="Application.init" default="yes">
<cfif Application.Init is "yes"> 
  <---Query-ausfuehren---->
  <cfquery name="artikel" datasource="die_datenbank">
    select titel,preis,anzahl, bestellnr from artikel
  </cfquery>
  <---speichern--->
  <cfset Application.ArtikelCache=Artikel>
  <---flag wird gesetzt--->
  <cfset Application.Init="no"> 
</cfif>
<---Application-Variable enthaelt hier immer das korrekte
Recordset!---> 

Soweit so gut, was macht man aber nun, wenn die Daten in der Datenbank sich ändern, z. B. wenn am Monatsanfang neue Artikel eingeliefert werden?

Man setzt einfach Application.init auf "yes" oder irgend einen anderen Wert. Dann wird beim nächsten Aufruf einer Seite die Abfrage erneut an die Datenbank geschickt und der aktuelle Artikelsatz geholt.

Man kann sich dazu eine Art init-Script schreiben in dem dann

<cfset Application.Init=0>

steht und das man entweder per Hand im Browser oder über eine Administratorseite aufruft.

Einen Nachteil hat dieses Verfahren aber doch. Die Datensätze/Applicationvariablen werden im Memory des ColdFusion-Servers gespeichert. Will man viele Querys oder riesige Datenmengen cachen, wird der Speicher knapp, was zu einer Verlangsamung von ColdFusion führt.



Steffen Goldfuss steffen@goldfuss.de - 14.10.2000

Zurück


Das deutsche ColdFusion-Forum cfml.de ist das Portal für Einsteiger und Experten zum Thema ColdFusion und der ColdFusion Markup Language (CFML).

© 2017 Webdesign & Hosting: CHC ONLINE Kassel | SOLVA Content-Management-System CMS
Urlaub-Angebote.de - Urlaub mit Bestpreis-Garantie buchen