Den APEX Regions-Cache nutzen

Bereits seit einiger Zeit bietet APEX die Möglichkeit an, die Inhalte von Regionen in einem eigenen Cache zu speichern. Dies ist beispielsweise für längerlaufende Berichte interessant. Wenn ein solcher Bericht einige Sekunden benötigt, (weil er auf größeren Datenmengen arbeitet), so leidet der gesamte Seitenaufbau darunter - die Anwendung wird träge. Regions-Caching kann hier hilfreich sein. APEX speichert den HTML-Code des Berichts dann in einem eigenen Cache ab und nutzt diesen beim nächsten Seitenaufbau - das geht natürlich sehr schnell. Zusätzlich zu Regionen lassen sich auch ganze Seiten cachen, am interessantesten ist jedoch mit Sicherheit das Caching auf Ebene der Region.

Auf der anderen Seite bringt ein Cache stets das Problem mit, dass veraltete Daten ausgeliefert werden könnten - und das gilt insofern auch für den APEX Regions-Cache. In diesem Tipp erfahren Sie daher nicht nur, wie man den Cache aktiviert, sondern auch, für welche Gelegenheiten er sich eignen könnte und wie man den Cache bei Bedarf richtig invalidieren kann.

Regions-Caching einrichten

Um mit dem Cache "spielen" zu können. benötigen Sie zunächst einen länger laufenden Bericht. Spielen Sie die folgende PL/SQL-Funktion ein, die dann im Bericht verwendet werden soll. Sie arbeitet mit DBMS_LOCK.SLEEP - Sie können also im Parameter P_SLEEP festlegen, wie lange "der Bericht" laufen soll. Damit die Funktion laufen kann, benötigen Sie EXECUTE-Privilegien auf dem Paket DBMS_LOCK.

create or replace function testcache (
  p_sleep in number
) return varchar2 is
begin
  dbms_lock.sleep(p_sleep);
  return 'Diese Nachricht ist vom '||
         to_char(sysdate, 'DD.MM.YYYY HH24:MI:SS')||
         ' und benötigte '||
         p_sleep||
         ' Sekunden.';
end;
/

Erzeugen Sie anschließend eine APEX-Anwendung mit einer Berichtsseite. Verwenden Sie das folgende Berichts-SQL.

select testcache(2) from dual

Navigieren Sie danach in der Regionsdefinition zum Bereich Caching (Abbildung 1). Normalerweise wird eine Region Nicht gecacht. Sie können die Region nun einmal für alle Nutzer in den Cache legen oder für die Nutzer individuell cachen. Sobald die Inhalte der Region in irgendeiner Weise vom angemeldeten Benutzer abhängen, müssen Sie die Einstellung Gecacht pro Benutzer nehmen; nur bei Regionen, die für alle Nutzer gleich aussehen, können Sie das einfache Gecacht verwenden.

Danach stellen Sie ein, wie alt die Inhalte im Cache maximal werden dürfen. Die möglichen Werte reichen von 10 Sekunden bis zu einem Jahr. Schließlich können Sie eine Bedingung festlegen. Das Beispiel in Abbildung 1 legt fest, dass kein Cache verwendet wird, wenn der APEX-Nutzer MANAGER angemeldet ist.

Caching einer APEX-Region: Einstellungen
Abbildung 1: Caching einer APEX-Region: Einstellungen

Anwendungsbeispiel 1: Kurzzeit-Cache für Navigationsfehler

Insbesondere die "10 Sekunden" können interessant sein. Denn viele Nutzer klicken in Anwendungen gerne hin und her. Man denke sich eine Anwendungsseite mit einem langlaufenden Bericht. Der Nutzer klickt nun, ausgehend von dieser Berichtsseite, eine Reiterkarte oder einen Link - auf der Zielseite stellt er fest, dass dies falsch war und navigiert zurück. Der langlaufende Bericht nun nun nochmal ausgeführt, das verbraucht CPU-Ressourcen und der Nutzer muss wieder warten.

Hier kann ein Regions-Cache mit einer Dauer von 10 Sekunden helfen. In sehr vielen Anwendungen dürfte es überhaupt nichts ausmachen, wenn ein Bericht "10 Sekunden alte Daten" anzeigt. Und besonders Folgen der beschriebenen Navigationsfehler lassen sich mit dem Regions-Cache ganz bequem abfangen.

Anwendungsbeispiel 2: Cache-Invalidierung für den Endbenutzer

Möchte man Regionsinhalte für längere Zeiträume cachen, so steht man vor dem Problem, dass es eigentlich keine "richtige" Dauer gibt. Cacht man die Informationen eine Stunde lang, so kann es bereits nach 10 Minuten passieren, dass ein Endbenutzer auf aktuellste Daten angewiesen ist. Nun lassen sich die APEX-Caches mit Prozeduren aus dem Paket APEX_UTIL auch programmatisch invalidieren, die Frage ist nur, wie man hier vorgeht.

  • Speziell für Berichte wäre die Variante denkbar, den Cache nach Änderungen an den Tabellen, auf denen der Bericht aufbaut, zu invalidieren. Hierfür ist der APEX Regions Cache jedoch ungeeignet - der in Oracle11g eingeführte Result Cache ist hier wesentlich besser geeignet und in diesem Community-Tipp näher beschrieben. Dieser arbeitet übrigens vollautomatisch - man muss sich über Invalidierungen gar keine Gedanken machen.
  • Der andere Ansatz basiert darauf, dem Anwender die gecachten (und unter Umständen veralteten) Daten zu zeigen, diesem jedoch die Möglichkeit zu geben, den Cache zu invalidieren. Die meisten Anwender dürften damit einverstanden sein, gecachte Daten zu sehen, solange Sie darüber informiert werden und die Möglichkeit haben, (durch Klick auf eine Schaltfläche) den aktuellen Datenstand zu sehen. Dieser Ansatz ist das Mittel der Wahl, wenn sich die zugrundeliegenden Daten häufig ändern und man dennoch mit einem Cache arbeiten möchte.

Stellen Sie also das Caching des Berichts auf ein größeres Zeitintervall (bspw. eine Stunde) ein und speichern Sie ihn ab. Nun geht es daran, dem Anwender die Information über den Cache-Status der Region zu geben. Dazu benötigen Sie ein ausgeblendetes Seitenelement PX_CACHE_DATE und einen PL/SQL-Seitenprozeß, der beim Laden der Seite ausgelöst wird und den Zeitstempel ermittelt, zu dem die Region zuletzt generiert und in den Cache gelegt wurde. Verwenden Sie folgenden PL/SQL-Code:

begin
  :PX_CACHE_DATE := to_char(
     APEX_UTIL.CACHE_GET_DATE_OF_REGION_CACHE(
       p_application => :APP_ID, 
       p_page        => 1,
       p_region_name => 'Bericht'
     ),
     'DD.MM.YYYY HH24:MI:SS'
  );
end;

Die Funktion APEX_UTIL.CACHE_GET_DATE_OF_REGION_CACHE gibt den Zeitstempel, wann die Region zuletzt generiert und in den Cache gelegt wurde, als DATE zurück. Als Parameter werden Anwendungs-ID, Seitennummer und der Name der Region (hier "Bericht") verwendet. Ist dazu kein Inhalt im Cache vorhanden, liefert die Funktion NULL zurück. Da der PL/SQL-Prozeß beim Laden der Seite, also vor dem Generieren der Region, ausgelöst wird, kann man an der Rückgabe erkennen, ob die Region aus dem Cache kommt (ein Zeitstempel) oder nicht (NULL).

Nun geht es daran, dem Anwender die Information zu präsentieren. Legen Sie dazu eine Region vom Typ HTML an und hinterlegen Sie folgenden HTML-Code als Regionsquelle.

Diese Daten kommen aus dem Cache und tragen den Zeitstempel &PX_CACHE_DATE..

Die Region soll nur angezeigt werden, wenn PX_CACHE_DATE nicht NULL ist (Abbildung 2). Dadurch wird die Information zum Cache nur dann angezeigt, wenn die Berichtsregion tatsächlich aus dem Cache kommt. Wenn Sie neu generiert wurde, wird nichts dargestellt.

Die Region mit der Cache-Information wird nur dargestellt, wenn der Bericht aus dem Cache kommt.
Abbildung 2: Die Region mit der Cache-Information wird nur dargestellt, wenn der Bericht aus dem Cache kommt.

Abbildung 3 zeigt, die Anwendungsseite, wenn die Region neu geladen wurde. Wenn der Cache zum Einsatz kommt, wird zusätzlich die Cache-Information dargestellt (Abbildung 4).

Anwendungsseite mit generierter Berichtsregion - die Inhalte sind aktuell
Abbildung 3: Anwendungsseite mit generierter Berichtsregion - die Inhalte sind aktuell
Anwendungsseite mit Berichtsregion aus dem Cache
Abbildung 4: Anwendungsseite mit Berichtsregion aus dem Cache

Damit ist der Anwender informiert. Fehlt noch die Möglichkeit, den Cache bei Bedarf zu invalidieren. Fügen Sie also zunächst eine Schaltfläche RESET_CACHE mit dem Label Cache leeren und dann einen PL/SQL-Prozeß hinzu. Der PL/SQL-Prozess soll beim Weiterleiten der Seite ausgeführt werden und enthält folgenden PL/SQL-Code.

begin
  apex_util.purge_regions_by_name (
    p_application => :APP_ID,
    p_page        => 1,
    p_region_name => 'Bericht'
  );
end;

Denken Sie an die Bedingung für den Prozess: Er wird natürlich nur ausgeführt, wenn die Schaltfläche geklickt wurde. Überprüfen Sie nochmal, ob die Verzweigung auf die gleiche Seite vorhanden ist und starten Sie die Seite neu. Zunächst sieht sie wie in Abbildung 5 aus ...

Anwendungsseite mit Berichtsregion aus dem Cache
Abbildung 5: Anwendungsseite mit Berichtsregion aus dem Cache

Abbildung 5 ähnelt sehr stark der Abbildung 4, nur dass nun zusätzlich die Schaltfläche zum Leeren des Cache vorhanden ist. Der Endanwender bekommt gute Performance; die Seite ist schnell aufgebaut. Er sieht sofort, dass die Daten veraltet sind. Aber anhand des exakten Zeitstempels kann er einschätzen, ob die Aktualität vielleicht dennoch hinreichend ist. Wünscht er aktuelle Daten, muss er nur auf die Schaltfläche Cache leeren klicken. Wie Sie an der Laufzeit erkennen können, wird die Seite nun neu generiert; das Ergebnis ist in Abbildung 6 darstellt. Es ist keine Cache-Information enthalten; die Daten sind also aktuell.

Anwendungsseite mit generierter Berichtsregion - die Inhalte sind aktuell
Abbildung 6: Anwendungsseite mit generierter Berichtsregion - die Inhalte sind aktuell

Fazit

Die meisten Entwickler sind sehr vorsichtig mit dem Einsatz von Caches und das aus gutem Grund: Wenn veraltete Daten ausgeliefert und Endanwender dadurch bei ihrer Arbeit behindert werden, so ist das schlicht nicht akzeptabel. Besonders wenn das Erstellen einer APEX-Region sehr aufwändig und teuer ist (komplexe Berichte), kann der APEX Regions-Cache dennoch interessant sein.

Werden längere Cache-Zeiten eingestellt (wenn die Endanwender also "richtig veraltete" Daten sehen könnten) sind zwei Dinge jedoch von enormer Wichtigkeit: Zum einen muss das Caching offen, sichtbar und nachvollziehbar gestaltet werden. Wenn man dem Anwender erstens "sagt", dass ein Cache zum Einsatz kommt, erspart man ihm das Kopfzerbrechen über die Daten ("Warum sehe ich meine Änderungen nicht ...?"). Zweitens muss er die Möglichkeit haben, aktuelle Daten anzufordern und den Cache zu umgehen. Der Seitenaufbau wird dann zwar länger dauern, das wird dann aber mit Sicherheit akzeptiert werden.

Zurück zur Community-Seite