Tuning-Rezepte für APEX-Anwendungen in der Cloud

Werbung
Jedes Byte zählt.
Tuning-Rezepte für
APEX-Anwendungen in der Cloud
Andreas Wismann
WHEN OTHERS
Beratung | Projektmanagement | Coaching
rund um Oracle Application Express
[email protected]
WHEN OTHERS
Beratung | Projektmanagement | Coaching
rund um Oracle Application Express
Andreas Wismann
Dipl.-Informatiker (FH)
http://when-others.com
[email protected]
+49 176 7800 3109
+49 2131 314 9966
@whenothers
Wo kann man optimieren?
• Webserver
• Datenbank-Konfiguration
• APEX-Konfiguration
• Datenübertragung
• Menge an HTML-Code
• Menge an Daten
• Geschwindigkeit der Skripte
(SQL, PL/SQL, HTML, CSS,
JavaScript)
Wo kann man optimieren?
Webserver
Datenbank-Konfiguration
APEX-Konfiguration
Datenübertragung
• Menge an HTML-Code
• Menge an Daten
• Geschwindigkeit der Skripte
(SQL, PL/SQL, HTML, CSS,
JavaScript)
 Cloud?
• oft wenig/kein Einfluss auf die Parameter des
Webservers, der Datenbank und der APEX-Instanz
• Einfluss auf die Programmierung
• "echte" Performance
• "gefühlte Performance"
Tuning-Rezepte…
ALTER SESSION
SET FAST=TRUE
messen…
• wie "groß" ist meine Seite?
• wie "schnell" ist
meine Seite?
• Responsezeiten
mit dem Kunden
festlegen
Welche Region ist langsam?
• Session Debug View zeigt die Prozessdauer an
#TIMING#
Welche Region ist langsam?
• Substitutionsvariable #TIMING#
in jeden Region Footer einbauen
10 Sekunden tippen
#ROWS_FETCHED# von #TOTAL_ROWS# Zeile(n)
abgerufen in #TIMING# Sekunden
SQL des Schreckens
declare
v_count number;
begin
select
into
from
where
count(*)
v_count
tabelle
gueltig_bis < sysdate;
if v_count > 0 then
delete from tabelle
where gueltig_bis < sysdate;
end if;
end;
Langläufer-SQL
• kritisch hinterfragen
• optimieren
• schon auf Seite 100 (während LOGIN) ausführen
Regelmäßiger Code-Review
Langsame Interaktive Reports
• Report erscheint nicht sofort beim Öffnen der Seite
• Browser reagiert nicht
• subjektives Empfinden: »APEX ist schuld«
• besser wäre: »der Report ist schuld«
• Ziel: verhindern, dass Benutzer beim Aufruf
einer Seite warten müssen
Langsame Interaktive Reports
• Hidden Item in die WHERE-Klausel einbauen:
… where :P1000_SHOW_SQL > 0
and …
• Default-Anfangswert: 0 oder NULL
• Durch Interaktion auf 1 setzen
30 Minuten
Programmieren &Testen
Lang laufende Sub-Selects
• Subselect:
… where ID
)
in (
SELECT ID FROM … where … IN (…, …)
• Subselect ersetzen durch Wertemenge in
APEX_COLLECTIONS:
… where
ID in (
select n001
from APEX_COLLECTIONS
where collection_name = 'SUBSELECT_1'
)
Lang laufende Sub-Selects
• SQL-Zwischenergebnisse in APEX_COLLECTIONS parken
APEX_COLLECTION.CREATE_COLLECTION_FROM_QUERY (
p_collection_name => 'Subselect 1',
p_query
=> 'SELECT ID FROM …');
• Individuelle Zwischenergebnisse
pro Benutzer verwenden
• ins Thema einlesen
• 15 Minuten Programmierung
Viele / große Web-Dateien
• JavaScript- und CSS-Dateien verzögern das Laden
der ersten Anwendungsseite
• Bilder erscheinen mit Verspätung
• Seite flackert
Viele / große Web-Dateien
Viele / große Web-Dateien
• Sämtliche Dateien auf der LOGIN-Seite vorausladen
(Template anpassen)
• CDN (Content Delivery Network) verwenden
• CSS-Sprites oder Icon-Fonts einsetzen, wenn viele
Icons geladen werden ("Font Awesome")
• 5 Minuten Programmierung
• 1 Klick
"For Your Eyes Only"
• zum Beispiel eine Region, die Table Statistics
anzeigt, auf Page 0 (Global Page) anlegen
• nur für Entwickler, per Authorization Scheme:
RETURN
apex_application.g_edit_cookie_session_id
IS NOT NULL;
• Report: 5 Minuten
• Authorization Scheme: 2 Minuten
Caching
• Das "Dashboard" lädt langsam
• ausgerechnet die Haupt-Anwendungsseite…
• viele Benutzer unterwegs
• große Datenmengen werden abgefragt
Caching
Caching
Caching
APEX_UTIL.CACHE_GET_DATE_OF_REGION_CACHE(
p_application => :APP_ID,
p_page
=> 1,
p_region_name => 'MY TABLES'
),
Caching
Caching
• Ziehen Sie das APEX Region Caching in Erwägung
• Invalidieren Sie den Cache beizeiten:
APEX_UTIL.PURGE_REGIONS_BY_NAME
APEX_UTIL.PURGE_REGIONS_BY_PAGE
• Insbesondere der Kurzzeit-Cache (10 Sek.)
beschleunigt Seiten für "herumklickende" Benutzer
2 Klicks
Viele Regionen oder Items mit
gleichen Conditions
• zwei oder mehr Regionen haben die ähnliche
Conditions
• Conditions sind komplex
Viele Regionen oder Items mit
gleichen Conditions
Viele Regionen oder Items mit
gleichen Conditions
• Parent-Region mit dieser Condition erstellen
(logischer Container)
• andere Regionen und Items unterordnen
• Parent-Region hat selbst kein "sichtbares" Template
• DRY
"Aufräumen": 15 Minuten pro Seite
Bedingungen für Prozesse
if ist_vertrag_gueltig
(:P500_VERTRAGSNUMMER) = TRUE
and :P500_KUNDENNUMER IS NOT NULL
then
-- viel Code, viele Aktionen …
select … ;
select … ;
end if;
Bedingungen für Prozesse
if ist_vertrag_gueltig
(:P500_VERTRAGSNUMMER)
and :P500_KUNDENNUMER IS NOT NULL
then
-- viel Code, viele Aktionen …
select … ;
select … ;
end if;
Bedingungen für Prozesse
if ist_vertrag_gueltig
(:P500_VERTRAGSNUMMER)
and :P500_KUNDENNUMER IS NOT NULL
then
-- viel Code, viele Aktionen …
select … ;
select … ;
end if;
Bedingungen für Prozesse
if :P500_KUNDENNUMER IS NOT NULL
and ist_vertrag_gueltig
(:P500_VERTRAGSNUMMER)
then
-- viel Code, viele Aktionen …
select … ;
select … ;
end if;
Bedingungen für Prozesse
if :P500_KUNDENNUMER IS NOT NULL
and ist_vertrag_gueltig
(:P500_VERTRAGSNUMMER)
then
-- viel Code, viele Aktionen …
select … ;
select … ;
end if;
Bedingungen für Prozesse
if :P500_KUNDENNUMER IS NOT NULL
and ist_vertrag_gueltig
(:P500_VERTRAGSNUMMER)
then
-- viel Code, viele Aktionen …
select … ;
select … ;
end if;
Bedingungen für Prozesse
if ist_gueltige_kundennummer(:P500_KUNDENNUMMER)
then
-- viel Code, viele Aktionen …
select … ;
select … ;
end if;
Bedingungen für Prozesse
• Äußere Bedingungen?
IMMER als Condition definieren
• Erspart unnötiges Parsen des Programmcodes
• APEX wertet Conditions sehr schnell aus
• Shortcut-Bedingungen im Programmcode
an die erste Stelle platzieren
• zusätzlich: keine
Testen auf Langsamkeit
BEGIN
DBMS_LOCK.SLEEP (10); -- 10 Sekunden
END;
-- üblicherweise nicht auf PUBLIC gegranted
BEGIN
APEX_UTIL.PAUSE (10); -- max. 120 Sekunden
END;
-- PUBLIC darf das ausführen!
Schnelle HTML-Tabellen
• SQL-Abfrage in einem Package ausführen
• Alle Zeilen per PL/SQL-Loop durchlaufen
• Jede Zeile als HTML formulieren
• gesamtes Tabellen-HTML zum Browser senden
Schnelle HTML-Tabellen
htp.p ('<table>');
for c in (SELECT … ) loop
htp.p ('<tr>'
|| '<td>' || c.spalte1 || '</td>'
|| '<td>' || c.spalte2 || '</td>'
|| '</tr>');
end loop;
htp.p ('</table>');
Schnelle HTML-Tabellen
• Reports,
• die der Benutzer nicht konfigurieren muss
• die nicht auf APEX Report-Feeatures angewiesen sind
• … direkt per HTML aus der Datenbank ausgeben
30 Minuten pro Report
Ladebalken
• Einige Prozesse lassen sich nicht beschleunigen
• Warten??? verunsichert die Benutzer
• der Browser wird unbedienbar
Ladebalken
• Langlaufender Prozess gestartet mittels
DBMS_SCHEDULER.CREATE_JOB
• Status-Updates per
DBMS_APPLICATION_INFO.SET_SESSION_LONGOPS
schreiben
• Status per V$SESSION_LONGOPS auslesen
• geJOINT mit Details in benutzerdefinierter Tabelle
("PROCESSING_STEPS")
• per AJAX Ladebalken und Statusreport aktualisieren
Demo
Menüvolumen verringern
• Original-HTML eines Links:
<li><a href="f?p=125:3:8629145276863:::::">zur Seite 3</a></a></li>
(67 Zeichen)
• gemeinsame Informationen für alle Seiten:
Server, Session-ID
f?p=,125,8629145276863
(22)
• individuelle Informationen pro Seite:
Seitennummer, Seitentitel
3,zur Seite 3
(14 inkl. Komma und Zeilenvorschub)
 APEX-Menüliste mit 100 Seiten:
67 kB
 Ersetzungsverfahren:
1400 Byte + ein jQuery-Skript
 Ersparnis: > 60 kB pro Seitenaufruf
Menüvolumen verringern
übertragen
1,zur Seite 1
2,zur Seite 2
3,zur Seite 3
4,zur Seite 4
5,zur Seite 5
6,zur Seite 6
7,zur Seite 7
8,zur Seite 8
9,zur Seite 9
10,zur Seite 10
11,zur Seite 11
12,zur Seite 12
13,zur Seite 13
14,zur Seite 14
15,zur Seite 15
16,zur Seite 16
17,zur Seite 17
18,zur Seite 18
19,zur Seite 19
20,zur Seite 20
per Skript berechnen
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
<li><a
href="f?p=125:1:8629145276863:::::">zur Seite 1</a></a></li>
href="f?p=125:2:8629145276863:::::">zur Seite 2</a></a></li>
href="f?p=125:3:8629145276863:::::">zur Seite 3</a></a></li>
href="f?p=125:4:8629145276863:::::">zur Seite 4</a></a></li>
href="f?p=125:5:8629145276863:::::">zur Seite 5</a></a></li>
href="f?p=125:6:8629145276863:::::">zur Seite 6</a></a></li>
href="f?p=125:7:8629145276863:::::">zur Seite 7</a></a></li>
href="f?p=125:8:8629145276863:::::">zur Seite 8</a></a></li>
href="f?p=125:9:8629145276863:::::">zur Seite 9</a></a></li>
href="f?p=125:10:8629145276863:::::">zur Seite 10</a></a></li>
href="f?p=125:11:8629145276863:::::">zur Seite 11</a></a></li>
href="f?p=125:12:8629145276863:::::">zur Seite 12</a></a></li>
href="f?p=125:13:8629145276863:::::">zur Seite 13</a></a></li>
href="f?p=125:14:8629145276863:::::">zur Seite 14</a></a></li>
href="f?p=125:15:8629145276863:::::">zur Seite 15</a></a></li>
href="f?p=125:16:8629145276863:::::">zur Seite 16</a></a></li>
href="f?p=125:17:8629145276863:::::">zur Seite 17</a></a></li>
href="f?p=125:18:8629145276863:::::">zur Seite 18</a></a></li>
href="f?p=125:19:8629145276863:::::">zur Seite 19</a></a></li>
href="f?p=125:20:8629145276863:::::">zur Seite 20</a></a></li>
Große Selectlisten
<select name="f04" id="f04_0000">
<option
<option
<option
<option
<option
value="1"
value="2"
value="3"
value="4"
value="5"
>Dokument
>Dokument
>Dokument
>Dokument
>Dokument
mit
mit
mit
mit
mit
der
der
der
der
der
…
…
…
…
…
…
</select>
Demo
250 Einträge:
14 kb pro Selectliste
200 kB pro Seitenaufruf
Nummer
Nummer
Nummer
Nummer
Nummer
1</option>
2</option>
3</option>
4</option>
5</option >
Große Selectlisten
function selectlistenErsetzen () {
var selectListOriginal = $('#P4_SELECTLIST_ORIGINAL');
// finde die Selectlisten im Tabular Form
$('td[headers="DOKUMENT_ID"] select')
.each(function() {
// … und ersetze die Dummys mit dem Original:
$(this).html( selectListOriginal.html() );
// richtige Auswahl einstellen …
});
}
Prozesse
• alles was "länger ist als drei Zeilen"
 in die Datenbank verlagern
 einzeilig im APEX-Prozessfenster aufrufen
Pipelined Function
• zur Aufspaltung in "einfachen" und "teuren" Teil
eines Reports
• zur Vereinfachung von überkomplexem SQL-Code
• wenn Sie den Ausführungsplan nicht in den Griff
bekommen
Templates vereinfachen
• APEX-Templates bieten viele Features
• sind auf Funktionalität, Komfort und Optik
optimiert
… auf Kosten der HTML-Effizienz?
… auf Kosten der Ladezeit?
last but not least
• gute Tools beschleunigen den Entwicklungszyklus
(anderer Aspekt, aber nicht weniger wichtig)
• Debugging abschalten
• statische Conditions in Build Options umwandeln
Buchempfehlung
• Steve Souders
• 2009
• 244 Seiten
• Sehr viele Anregungen
rund um die
technische Architektur
von Webseiten
WHEN OTHERS
Beratung | Projektmanagement | Coaching
rund um Oracle Application Express
Andreas Wismann
Dipl.-Informatiker (FH)
http://when-others.com
[email protected]
+49 176 7800 3109
+49 2131 314 9966
@whenothers
Herunterladen