Daily CheckIn

This commit is contained in:
marcodn 2024-09-28 13:33:24 +02:00
parent 1f34a0a382
commit 94600c6f2a
12 changed files with 121 additions and 124 deletions

View file

@ -59,7 +59,7 @@ den darzustellenden Datenbestand abgeschickt.
Die Datenanfragen werden über die \textit{Enterprise Java Beans} an die \textit{Java Persistance API} weitergeleitet.
Hier wird nun geprüft, ob die Daten aus dem \textit{OpenJPA Cache} direkt ermittelt werden können, oder ob die Abfrage
an das unterlagerte Datenbankmanagementsystem \textit{PostgreSQL} weitergeleitet werden muss. Die ermittelten Daten vom
DBMS werden bei Bedarf im \textit{OpenJPA Cache} aktualisiert.
\ac{DBMS} werden bei Bedarf im \textit{OpenJPA Cache} aktualisiert.
Das \textit{PostgreSQL} besteht aus mehreren Teilen die ineinander greifen um die Anfragen zu bearbeiten.
Dabei sind die \textit{Memory Buffers} notwendig um den Zugriff auf die Festplatte zu reduzieren, um die Bearbeitungszeit

View file

@ -8,12 +8,12 @@
\chapter{Aufruf Skript}
\label{ap:calling_script}
Um die Messungen etwas zu vereinfachen wurde ein Skript erstellt um die Aufrufe gesammelt durchzuführen. Um die
Messungen durchzuführen werden die Befehl, wie in \autoref{lst:calling_script_exec} dargestellt aufgerufen.
Um die Messungen etwas zu vereinfachen, wurde ein Skript erstellt, um die Aufrufe gesammelt durchzuführen. Um die
Messungen durchzuführen, werden die Befehle, wie in \autoref{lst:calling_script_exec} dargestellt aufgerufen.
Durch die nummerierten Präfixe können im Nachgang über die \textit{pgBadger}"=Berichte die \ac{SQL}"=Abfragen verglichen
werden. Wichtig hierbei ist noch, dass vor dem \textit{measrun}-Aufruf überprüft wird, ob die Docker-Container
gestartet und initialisiert sind. Wenn dies nicht der Fall ist, laufen die Abfragen ins Leere. Am einfachsten ist das,
wie dargestellt, über die Statistik von Docker zu ermitteln. Darüber wird überwacht, das die CPU-Auslastung auf ein
wie dargestellt, über die Statistik von Docker zu ermitteln. Darüber wird überwacht, dass die CPU-Auslastung auf ein
niedriges Level fällt, danach kann das Skript für die Messungen aufgerufen werden.
\includecode[bash]{chapters/thesis/appendix04_calling_script.sh}{lst:calling_script}{Calling Script}

View file

@ -27,7 +27,7 @@ um eine längere Bearbeitung anzuzeigen.
Die Grundlage zu dieser Arbeit bildet das DFG-Projekt \glqq Edition der Korrespondenz Frank Wedekinds als Online"=Volltextdatenbank\grqq.
Die folgende Übersicht hierzu ist eine Anlehnung an \citep{EffwFrankWedekind}.
Die Editions- und Forschungsstelle Frank Wedekind (EFFW) wurde 1987 in der Hochschule Darmstadt gegründet. Ihre Intention
Die Editions"= und Forschungsstelle Frank Wedekind (EFFW) wurde 1987 in der Hochschule Darmstadt gegründet. Ihre Intention
ist es, den lange vernachlässigten Autor der europäischen Moderne in die öffentliche Aufmerksamkeit zu bringen. Die
Publikation der >>Kritischen Studienausgabe der Werke Frank Wedekinds. Darmstädter Ausgabe<<
wurde direkt nach der Erschließung der Wedekind-Nachlässe in Aarau, Lenzburg und München begonnen und im Jahre
@ -43,7 +43,7 @@ und 1918, indem das überlieferte Material zum einen transkribiert editiert und
kommentiert wurde.
Um jenes zu verändern entstand das Projekt >>Edition der Korrespondenz Frank Wedekind als Online"=Volltextdatenbank<<,
welches bei der EFFW angesiedelt ist und als Kooperationsprojekt an der Johannes Gutenberg"=Universität Mainz,
welches bei der EFFW angesiedelt ist und als Kooperationsprojekt an der Johannes Gutenberg"=Universität Mainz,
der Hochschule Darmstadt und der Fernuni Hagen umgesetzt und durch die Deutsche Forschungsgemeinschaft (Bonn) gefördert wird.
Das entstandene Pilotprojekt ist eine webbasiert Anwendung, die aktuell unter \url{http://briefedition.wedekind.h-da.de}

View file

@ -10,7 +10,7 @@ geht durch mehrere Schichten des Server"=System bis die Antwort an den Client zu
Es wird ab hier von einem \textit{Glassfish}"=Server die Rede sein. In der Praxis wird ein \textit{Payara}"=Server
verwendet. Der \textit{Glassfish}"=Server ist die Referenz"=Implementierung von Oracle, welche für Entwickler
bereitgestellt wird und neue Features unterstützt. Der \textit{Payara}"=Server ist aus dessen Quellcode entstanden
bereitgestellt wird und die neuesten Features unterstützt. Der \textit{Payara}"=Server ist aus dessen Quellcode entstanden
und ist für Produktivumgebungen gedacht, da dieser mit regelmäßigen Aktualisierungen versorgt wird. Im folgenden Text
wird der Begriff \textit{Glassfish} verwendet.
@ -22,7 +22,7 @@ für den darzustellenden Datenbestand abgeschickt.
Die Datenanfragen werden über die \textit{\ac{EJB}} an die \textit{\ac{JPA}} weitergeleitet.
Hier wird nun geprüft, ob die Daten aus dem \textit{OpenJPA Cache} direkt ermittelt werden können, oder ob die Abfrage
an das unterlagerte Datenbankmanagementsystem \textit{PostgreSQL} weitergeleitet werden muss. Die ermittelten Daten vom
DBMS werden bei Bedarf im \textit{OpenJPA Cache} aktualisiert.
\ac{DBMS} werden bei Bedarf im \textit{OpenJPA Cache} aktualisiert.
Das \textit{PostgreSQL} besteht aus mehreren Teilen die ineinander greifen, um die Anfragen zu bearbeiten. Dabei
sind die \textit{Memory Buffers} notwendig, um den Zugriff auf die Festplatte zu reduzieren und die Bearbeitungszeit
@ -99,7 +99,7 @@ Eine Menge von Objekten wird als \textit{Persistenzkontext} bezeichnet. Solange
\section{Glassfish - OpenJPA Cache}
\label{sec:basics:ojpac}
Zusätzlich kann im \textit{JPA} ebenfalls noch der \textit{Second Level Cache} (L2-Cache) aktiviert werden. Dieser steht
Zusätzlich kann im \textit{\ac{JPA}} ebenfalls noch der \textit{Second Level Cache} (L2-Cache) aktiviert werden. Dieser steht
jedem \textit{Persistenzkontext} zur Verfügung und kann dadurch die Anzahl der Datenbankzugriffe deutlich reduzieren,
was bei langsamen Datenbank"=Anbindungen zu hohen Performance"=Gewinnen führen kann \citep[171]{MüllerWehr2012}.
Zu Beachten ist, dass die Daten im \textit{Second Level Cache} explizit über die Änderungen informiert werden
@ -169,7 +169,7 @@ Für weitere Optimierungen werden anschließend die Anfragen einzeln überprüft
Ausführungspläne der Abfrage zu analysieren \citep[252]{Eisentraut2013}, die verschiedenen Plantypen und ihre Kosten zu
kennen sowie die angegeben Werte für die Plankosten zu verstehen \citep[24-30]{Dombrovskaya2021}.
Besonderes Augenmerk gilt dem Vergleichen des tatsächlich ausgeführten mit dem ursprünglichen Plan
\citep[254]{Eisentraut2013}. Eine \todo{eine oder eines?} der wichtigsten Kennzeichen hierbei ist, ob die Zeilenschätzung akkurat war.
\citep[254]{Eisentraut2013}. Eines der wichtigsten Kennzeichen hierbei ist, ob die Zeilenschätzung akkurat war.
Größere Abweichungen weisen häufig auf veraltete Statistiken hin.
Um die Abfragen selbst zu optimieren, gibt es ein Vorgehen über mehrere Schritte \citep[304-308]{Dombrovskaya2021}.

View file

@ -26,7 +26,7 @@ Der Speicher, der für eine Abfrage verwendet werden darf, wird über die Konfig
Wenn der Speicher zu gering wird, werden die Zwischenergebnisse in temporäre Dateien ausgelagert. Der empfohlene Wert
berechnet sich aus \texttt{shared\_buffers} dividiert durch \texttt{max\_connections} \citep{ConfigTo12:online}.
Sollte die Berechnung außerhalb der Grenzwerte von 1 MB und 256 MB liegen, ist der jeweilige Grenzwert zu verwenden.
Um zu ermitteln, ob die Konfiguration richtig ist, muss im PostgreSQL die Einstellung \texttt{log\_temp\_files} auf 0
Um zu ermitteln, ob die Konfiguration richtig ist, muss im PostgreSQL die Einstellung \texttt{log\_temp\_files} auf 0 %TODO: log_temp_files überschreitet den Rand
gesetzt werden. Mit dieser kann ermittelt, ob temporäre Dateien verwendet werden sowie deren Größe. Bei vielen kleineren
Dateien sollte der Grenzwert erhöht werden. Bei wenigen großen Dateien ist es ist sinnvoll den Wert so zu belassen.
@ -38,9 +38,9 @@ Nachfolgend wird mit dem Systemtools, wie den Konsolenanwendungen \textit{htop}
überprüft. Hierbei ist die CPU"=Leistung, der aktuell genutzte Arbeitsspeicher, sowie die Zugriffe auf die Festplatte
die wichtigen Faktoren zur Bewertung.
Die CPU"=Leistung sollte im Schnitt 70\% nicht überschreiten, für kurze Spitzen wäre dies zulässig. Um zu verhindern, dass der
Server an seiner Leistungsgrenze arbeitet und es dadurch nicht mehr schafft, die gestellten Anfragen schnell genug
abzuarbeiten.\todo{Satz überarbeiten}
Die CPU"=Leistung sollte im Schnitt 70\% nicht überschreiten, für kurze Spitzen wäre dies zulässig, um die gestellten
Anfragen schnell genug abarbeiten zu können. Daher soll verhindert werden, dass der Server an seiner Leistungsgrenze
arbeitet.
Da unter Linux der Arbeitsspeicher nicht mehr direkt freigegeben wird, ist hier die Page"=Datei der wichtigere Indikator.
Wenn dieses in Verwendung ist, dann benötigen die aktuell laufenden Programme mehr Arbeitsspeicher als vorhanden ist,
@ -63,11 +63,11 @@ Die Dokumentenliste zeigt direkte und indirekte Informationen zu einem Dokument
Dokumentes, das Schreibdatum, der Autor, der Adressat, der Schreibort und die Korrespondenzform. Nach jeder dieser
Informationen kann der Bediener die Liste auf"= oder absteigend sortieren lassen. Zusätzlich wird die Liste immer nach
dem Schreibdatum sortiert, um die Ergebnisse bei gleichen Werten der zu sortierenden Informationen, wie dem Schreibort,
immer in einer chronologisch aufsteigenden Form zu darzustellen.
immer in einer chronologisch aufsteigenden Form darzustellen.
Aktuell verwenden die Editoren die Dokumentenliste um die Briefe eines Adressaten zu filtern und diese in
chronologische Reihenfolge aufzulisten und zu untersuchen wie Kommunikation zwischen Herrn Wedekind und dem Adressaten
abgelaufen ist. Ebenso wird nach Standorten sortiert, um zu ermitteln welchen Personen sich im Zeitraum am gleichen
Aktuell verwenden die Editoren die Dokumentenliste, um die Briefe eines Adressaten zu filtern und diese in
chronologische Reihenfolge aufzulisten und zu untersuchen, wie die Kommunikation zwischen Herrn Wedekind und dem Adressaten
abgelaufen ist. Ebenso wird nach Standorten sortiert, um zu ermitteln, welche Personen sich im Zeitraum am gleichen
Ort aufgehalten haben.
Da die Daten in der 3. Normalform in der Datenbank gespeichert werden, sind einige Relationen für die Abfragen
@ -87,7 +87,7 @@ PostgreSQL"=Schicht wurde schon im vorherigen Kapitel betrachtet. Daher werden n
Glassfish"=Server in aufsteigender Reihenfolge betrachtet.
Die OpenJPA Cache Schicht wird nun einzeln untersucht. Hierfür werden zuerst die Cache"=Statistik für Object"=Cache
und Query"=Cache aktiviert \citep[315]{MüllerWehr2012}. Die somit erfassten Werte, werden über eine Webseite
und Query"=Cache aktiviert \citep[315]{MüllerWehr2012}. Die somit erfassten Werte werden über eine Webseite
bereitgestellt, um die Daten Live vom Server verfolgen zu können. Zusätzlich wird die Webseite über ein Script
aufgerufen und die Aufrufzeiten sowie andere externe Statistiken darüber erstellt und gespeichert.
@ -108,12 +108,13 @@ for(EntityType<?> entityType : em.getMetaModel().getEntities())
emf.getCache().print();
\end{lstlisting}
Die Schicht \ac{EJB} besitzt keine Möglichkeit um eine sinnvolle Messung durchzuführen, daher wird hierfür keine
Die Schicht \ac{EJB} besitzt keine Möglichkeit, um eine sinnvolle Messung durchzuführen, daher wird hierfür keine
direkte Messungen eingefügt. Hier werden nur die externen Statistiken durch das Skript verwendet, um zu prüfen in
welchen Umfang die Umstellungen eine Veränderung im Verhalten der Webseite bewirken.
Bei den \ac{JSF} wird eine Zeitmessung eingefügt. Um sich in die Verarbeitung der Seiten \todo{was ist an einzuhängen falsch?, das sich muss weg} einzuhängen, wird eine
\textit{Factory} benötigt. \todo{Umstellen weil 2x Ermitteln} In dieser werden die Zeiten zum Ermitteln der Daten, das Zusammensetzen und das Rendern
Bei den \ac{JSF} wird eine Zeitmessung einfügt, wofür eine \textit{Factory} benötigt wird. Diese wird in den Pipeline
Prozess, der die Verarbeitung der Seiten steuert, eingebunden und erstellt die Klasse für die Messung.
In dieser werden die Zeiten zum Ermitteln der Daten, das Zusammensetzen und das Rendern
der Sicht ermittelt. Die Zeiten werden in die Log"=Datei des \textit{Glassfish}"=Servers hinterlegt und durch das
Skript ausgewertet. Somit ist es relativ leicht aufzuzeigen, an welcher Stelle die größte Verzögerung auftritt.
@ -128,9 +129,9 @@ der Performance und der Abfragedauern verkürzen können.
Damit die Messungen nachvollziehbar bleiben, werden die Testaufrufe durch ein Bash-Script automatisiert gerufen.
Wichtig hierbei ist, dass die Webseite immer vollständig gerendert vom Server an den Client übertragen wird.
Somit kann die clientseitige Performance ignoriert werden, da alle Daten direkt in diesem Aufruf bereitgestellt
wird. In dem Skript werden zum einen die Laufzeiten der Webanfragen ermittelt,\todo{wie anders schreiben, zum einen - zum anderen} zum anderen die kürzeste, die längste und die
durchschnittliche Laufzeit ermittelt. Auf Grund der Speicherprobleme, werden auch die Speicherbenutzung des
Somit kann die clientseitige Performance ignoriert werden, da alle Daten bereits direkt in diesem einem Aufruf bereitgestellt
werden. In dem Skript werden zum einen die Laufzeiten der Webanfragen ermittelt, zum anderen die kürzeste, die längste und die
durchschnittliche Laufzeit ermittelt. Auf Grund der Speicherprobleme werden auch die Speicherbenutzung des
\textit{Glassfish}"=Servers vor und nach den Aufrufen ermittelt. Zum Schluss werden noch die Log"=Dateien des
\textit{PostgreSQL}"=Servers über das Tool \textit{pgBadger} analysiert und als Bericht aufbereitet.

View file

@ -44,7 +44,7 @@ Um eine Messung der Performance in der Webseite durchführen zu können, gibt es
eigene Implementierung der Klasse \texttt{ViewDeclarationLanguageWrapper} sich in das Generieren der Webseite
einzuhängen. Hierbei können die Funktionen für das Erstellen, das Bauen und das Rendern der Webseite überschrieben
werden. In den überschriebenen Funktionen werden nun Laufzeiten gemessen und die ermittelten Zeiten mit einer Kennung
in die Log"=Datei eingetragen. Durch die Kennung, können die Zeiten im Nachgang über ein Script ermittelt und
in die Log"=Datei eingetragen. Durch die Kennung können die Zeiten im Nachgang über ein Script ermittelt und
ausgewertet werden.
Zusätzlich wird noch eine Implementierung der zugehörigen Factory"=Klasse \texttt{ViewDeclarationLanguageFactory}
@ -106,12 +106,12 @@ Das Untersuchen der protokollierten Abfragen auf Performance Optimierungen ist e
Das Schlüsselwort \texttt{EXPLAIN} ist im PostgreSQL vorhanden, um den Abfrageplan einer Abfrage zu ermitteln und
darzustellen, um diese anschließend zu untersuchen. Der Abfrageplan ist als Baum dargestellt, bei welchem die Knoten die
unterschiedlichen Zugriffsarten darstellen. Die Verbindung der Knoten und der Aufbau zeigt die Operationen, wie
etwa Joins, Aggregierung und Sortierung, und die Reihenfolgen der Abarbeitung. Zusätzlich sind auch Zwischenschritte,
etwa Joins, Aggregierung und Sortierung, und die Reihenfolgen der Abarbeitung. Zusätzlich sind auch Zwischenschritte
wie Zwischenspeicherungen ersichtlich. Zu jeder Operation gibt es neben dem Typ noch zusätzliche Informationen, wie
die geschätzten Anlauf"= und Gesamtkosten (\textit{costs}), die geschätzte Anzahl der Zeilen (\textit{rows}) und die
geschätzte Breite jeder Zeile (\textit{width}). Der Wert von \textit{costs} wird bei übergeordneten Knoten summiert.
Bei der Option \texttt{ANALYZE} wird die Abfrage ausgeführt und die echten Werte und Laufzeiten angezeigt. Ohne diese,
Bei der Option \texttt{ANALYZE} wird die Abfrage ausgeführt und die echten Werte und Laufzeiten angezeigt. Ohne diese
wird nur der Plan erstellt und dargestellt. Durch \texttt{VERBOSE} wird der Abfrageplan um zusätzliche Informationen
angereichert. Die Option \texttt{BUFFERS} erweitert die Informationen über die Nutzung der Caches. Für eine
Zusammenfassung am Ende des Abfrageplans, gibt es die Option \texttt{summary}. Eine vereinfachte Form des Aufrufs
@ -124,13 +124,13 @@ EXPLAIN (ANALYZE, VERBOSE, BUFFERS, SUMMARY)
Die zwei bekanntesten Knotentypen sind \texttt{Seq Scan} und \texttt{Index Scan}. Wenn eine Tabelle Zeile für Zeile
gelesen wird, zeigt der Abfrageplan einen \texttt{Seq Scan}"=Knoten an. Hierbei entsteht, unabhängig davon ob eine
Bedingung zum filtern vorhanden ist, eine unsortierte Liste dessen Startkosten entsprechend niedrig sind. Je weiter die
Bedingung zum filtern vorhanden ist, eine unsortierte Liste, deren Startkosten entsprechend niedrig sind. Je weiter die
Liste durchlaufen wird, desto höher steigen die notwendigen Kosten. Die kostengünstigere Alternative ist der
\texttt{Index Scan}, bei dem der Index nach den Kriterien durchsucht wird, was meist durch den Aufbau des Index als
BTree (Multi"=Way Balanced Tree) rapide geht.
Eine weitere Optimierungsmöglichkeit ist die Verwendung von Indexen. Diese sind aber mit Bedacht zu wählen, da bei
mehreren Indexen die sehr ähnlich sind, nicht immer der gewünschte Index bei der Abfrage verwendet wird. Auch bedeutet
mehreren Indexen, die sehr ähnlich sind, nicht immer der gewünschte Index bei der Abfrage verwendet wird. Auch bedeutet
ein Index bei jeder Änderung der Daten zusätzliche Arbeit, da dieser entsprechend mit gepflegt werden muss und ebenso
dessen Statistik muss regelmässig aktualisiert werden. Ebenfalls ist die Reihenfolge der Spalte in einem
zusammengesetzten Index von Bedeutung. Als Grundlage sollte hier mit der Spalte gestartet werden, welche die größte
@ -140,19 +140,17 @@ Vergleichsoperation auf die Tabellenspalte zugegriffen wird.
Um größere und aufwendigere Abfragen zu optimieren, bietet der PostgreSQL noch die Möglichkeit von
\textit{Materialized View}. Diese sind sehr ähnlich zu den Sichten, zusätzlich werden aber die Ergebnisse in einer
tabellenähnlichen Form abgespeichert, somit sind die Zugriff auf diese Daten häufig performanter als die eigentliche Abfrage.
Daher muss abgewägt werden, ob die Performance-Verbesserung trotz der zusätzliche Aktualisierung des Datenbestandes
Daher muss abgewägt werden, ob die Performance-Verbesserung trotz der zusätzlichen Aktualisierung des Datenbestandes
als sinnvoll erachtet werden kann.
\mytodos{das doch wieder raus? oder nur das mit create statistics drin lassen}
Zusätzlich kann über die Systemtabelle \texttt{pg\_statistic} oder die lesbarere Systemsicht \texttt{pg\_stats} die
aktuelle statistischen Informationen über eine Tabelle und deren Spalten ermittelt werden. In dieser Tabelle werden
durch das \texttt{ANALYZE} beziehungsweise \texttt{VACUUM ANALYZE} Kommando die Informationen zum Anteil der
\texttt{NULL}"=Werte (null\_frac), Durchschnittlichen Größe (avg\_width), unterschiedlicher Werte (n\_distinct) und
\texttt{NULL}"=Werte (null\_frac), durchschnittlichen Größe (avg\_width), unterschiedlicher Werte (n\_distinct) und
weitere gesammelt und für die Erstellung der Abfragepläne verwendet \citep{PostgreS39:online}. Diese Information
sollte vor dem erstellen eines Index betrachtet werden.
Diese Informationen können noch durch das Kommando \texttt{CREATE STATISTICS} erweitert werden, für einen besseren
Diese Informationen können noch durch das Kommando \texttt{CREATE STATISTICS} erweitert werden, für einen besseren %TODO texttt zeigt über den Rand
Abfrageplan. Das Aktivieren der zusätzlichen Statistiken sollte immer in Verbindung mit der Überprüfung des
Abfrageplans durchgeführt werden, um zu ermitteln inwieweit die Anpassung zu einer Optimierung und keiner
Verschlechterung führt.

View file

@ -10,14 +10,14 @@ Für die Tests wird ein aktuelles Manjaro"=System mit frisch installierten Payar
als Entwicklungsumgebung verwendet. Der Computer ist mit einer Intel CPU i7-12700K, 32 GB Arbeitsspeicher und einer SSD
als Systemfestplatte ausgestattet.
Zur ersten Untersuchung und der Bestimmung der Basis-Linie, wurde das Script ohne eine Änderung am Code und der
Zur ersten Untersuchung und der Bestimmung der Basis-Linie wurde das Script ohne eine Änderung am Code und der
Konfiguration mehrfach aufgerufen. Hierbei hat sich gezeigt, dass der erste Aufruf nach dem Deployment circa 1500 ms
gedauert hat. Die weiteren Aufrufe benötigen im Durchschnitt noch 600 ms. Beim achten Aufruf des Scripts hat der
Server nicht mehr reagiert und im Log ist ein \textit{OutOfMemoryError} protokolliert worden.
Nach einem Neustart des Servers, konnte das gleiche Verhalten wieder reproduziert werden. Daraufhin wurde das Test"=Script
um die Anzeige der aktuellen Speicherverwendung des Payara"=Servers erweitert um diese zeitgleich zu beobachten. Diese
Auswertung zeigte, dass der Server mit circa 1500 MB RSS Nutzung an seine Grenzen stößt. Diese Grenzen wurde durch die
Nach einem Neustart des Servers konnte das gleiche Verhalten wieder reproduziert werden. Daraufhin wurde das Test"=Script
um die Anzeige der aktuellen Speicherverwendung des Payara"=Servers erweitert, um diese zeitgleich zu beobachten. Diese
Auswertung zeigte, dass der Server mit circa 1500 MB RSS Nutzung an seine Grenzen stößt. Diese Grenze wurde durch die
Konfigurationsänderung im Payara-Server von \texttt{-Xmx512m} auf \texttt{-Xmx4096m} nach oben verschoben. Nun werden
circa 60 Aufrufe des Scripts benötigt, damit der Server nicht mehr reagiert. Hierbei wird aber kein \textit{OutOfMemoryError}
in der Log-Datei protokolliert und der Server verwendet nun circa 4700 MB RSS. Bei allen Tests war noch mehr als die
@ -30,7 +30,7 @@ Arbeitsspeicher das Problem nicht löst, sondern nur verlagert.
Für alle nachfolgenden Messungen wird das Skript im \autoref{ap:calling_script} verwendet, welches die einzelnen
Aufrufe steuert. Die Ergebnisse werden in eine Tabelle überführt, wie in \autoref{tbl:measure-without-cache}.
Hierbei werden die Aufrufzeiten der Webseite aus dem Skript für die Zeitmessung mit Mindest"~, Durchschnitt"~ und
Maximalzeit aufgenommen, hierbei ist eine kürzere Zeit besser. Zusätzlich wird die Anzahl der aufgerufenen SQL Abfragen
Maximalzeit aufgenommen, hierbei ist eine kürzere Zeit besser. Zusätzlich wird die Anzahl der aufgerufenen \ac{SQL} Abfragen
ermittelt, auch hier gilt, je weniger Aufrufe desto besser. Als letztes wird noch der verwendete Arbeitsspeicher
vom \textit{Glassfish}"=Server vor und nach dem Aufruf ermittelt und die Differenz gebildet, hierbei sollte im idealen
Fall die Differenz bei 0 liegen. Dieser Aufbau gilt für alle weiteren Messungen. Zusätzlich werden noch die Laufzeiten
@ -41,7 +41,7 @@ Als Grundlage für die Vergleiche wurde eine Messung durchgeführt, bei welcher
Änderung am Code vorgenommen wurde. Das Ergebnis dieser Messung ist in \autoref{tbl:measure-without-cache} zu finden.
Diese zeigen auch direkt ein zu erwartendes Ergebnis, dass der erste Aufruf bedeutend länger dauert als die Nachfolgenden.
Ebenfalls sieht man eindeutig, dass die Anzahl der Anfragen nach dem ersten Aufruf immer die gleiche Anzahl besitzen.
Der Speicherbedarf steigt relative gleichmässig, was nicht recht ins Bild passt, da hier keine Objekte im Cache
Der Speicherbedarf steigt relativ gleichmässig, was nicht recht ins Bild passt, da hier keine Objekte im Cache
gehalten werden sollten.
\begin{table}[!h]
@ -114,21 +114,21 @@ der Java"=Objekte inklusive dem Befüllen mit den geladenen Daten.
Die Cache"=Einstellung von OpenJPA werden über die zwei Einstellungen \texttt{openjpa.DataCache} und
\texttt{openjpa.QueryCache} konfiguriert. Bei beiden Einstellungen kann zuerst einmal über ein einfaches Flag
\textit{true} und \textit{false} entschieden werden ob der Cache aktiv ist. Zusätzlich kann über das Schlüsselwort
\textit{true} und \textit{false} entschieden werden, ob der Cache aktiv ist. Zusätzlich kann über das Schlüsselwort
\textit{CacheSize} die Anzahl der Elemente im Cache gesteuert werden. Wird diese Anzahl erreicht, werden zufällige
Objekte aus dem Cache entfernt und in eine SoftReferenceMap übertragen. Bei der Berechnung der Anzahl der Elemente werden
angeheftete Objekte nicht beachtet.
Die Anzahl der Soft References kann ebenfalls über eine Einstellung gesteuert werden. Hierfür wird die Anzahl der
Elemente über \textit{SoftReferenceSize} gesetzt, dessen Wert im Standard auf \textit{unbegrenzt} steht. Mit dem Wert
\textit{0} werden die Soft Referenzen komplett deaktiviert. Über die Attribute an den Entitätsklassen, können diese
\textit{0} werden die Soft Referenzen komplett deaktiviert. Über die Attribute an den Entitätsklassen können diese
Referenzen ebenfalls gesteuert werden, hierzu muss eine Überwachungszeit angegeben werden. Diese Zeit gibt in ms an,
wie lange ein Objekt gültig bleibt. Mit dem Wert \textit{-1} wird das Objekt nie ungültig, was ebenfalls der
Standardwert ist.
Zuerst wird mit aktivierten Cache mit einer Cache-Größe von 1000 Elemente getestet. Wie in
Zuerst wird mit aktiviertem Cache mit einer Cache-Größe von 1000 Elemente getestet. Wie in
\autoref{tbl:measure-ojpa-active} zu sehen, dauert auch hier der erste Aufruf minimal länger als ohne aktiviertem
Cache. Alle Nachfolgenden Aufrufe wiederrum sind um 100ms schneller in der Verarbeitung. Auch bei der Anzahl der
Cache. Alle nachfolgenden Aufrufe wiederrum sind um 100ms schneller in der Verarbeitung. Auch bei der Anzahl der
Anfragen an die Datenbank kann der Rückgang der Anfragen sehr gut gesehen werden. Aktuell kann die Verringerung des
wachsenden Speicherbedarfs nur nicht erklärt werden.
@ -214,7 +214,7 @@ der Objekte den Cache übersteigt, fällt die Verbesserung geringer aus.
\label{sec:performance-investigation-application:cached-query}
Über die Einstellung \textit{openjpa.""jdbc.""QuerySQLCache} wird der Cache für Abfragen aktiviert. Hierbei können
Abfragen angeben werden, die aus dem Cache ausgeschlossen werden. Der QueryCache wiederrum beachtet aber nur Abfragen
Abfragen angeben werden, die aus dem Cache ausgeschlossen werden. Der QueryCache wiederrum beachtet aber nur Abfragen,
die keine Parameter verwenden. Das sieht man auch entsprechend der Auswertung der Aufrufe in
\autoref{tbl:measure-cached-queries}, dass hier keine Veränderung der Aufrufzeiten stattgefunden hat, gleich ob
mit \ac{JPQL} oder Criteria API abfragt wird.
@ -244,8 +244,7 @@ mit \ac{JPQL} oder Criteria API abfragt wird.
\section{Caching mit Ehcache}
\label{sec:performance-investigation-application:caching-ehcache}
\todo{hier weiter machen!!!!}
Der Ehcache ist ein L2"=Cache den man direkt in OpenJPA mit integrieren kann. Hierfür sind einige Punkte zu beachten.
Der Ehcache ist ein L2"=Cache, den man direkt in OpenJPA mit integrieren kann. Hierfür sind einige Punkte zu beachten.
Zum einen muss die Referenz auf das \textit{ehcache} und das \textit{ehcache"=openjpa} Paket hinzugefügt werden.
Zusätzlich dazu sind die Konfiguration \textit{openjpa.""QueryCache}, \textit{openjpa.""DataCache} und
\textit{openjpa.""DataCacheManager} auf \textit{ehcache} anzupassen. Anhand der Annotation \texttt{@DataCache} kann
@ -290,14 +289,14 @@ benötigt.
\label{sec:performance-investigation-application:caching-ejb}
Die Cache"=Einstellungen des \ac{EJB} sind in der Admin-Oberfläche des Payara-Servers zu erreichen. Unter dem Punkt
Configurations $\Rightarrow$ server"=config $\Rightarrow$ EJB Container werden zum einen die minimalen und maximalen
Configurations $\Rightarrow$ server"=config $\Rightarrow$ \ac{EJB} Container werden zum einen die minimalen und maximalen
Größen des Pools definiert werden. Zum anderen wird an dieser Stelle die maximale Größe des Caches und die Größe der
Erweiterung definiert.
Anhand der Auswertung der \autoref{tbl:measure-ejb-cache-active} ist ersichtlich, dass der \ac{EJB}"=Cache keine
Auswirkung auf die Performance hat. Ebenso ist es ersichtlich, dass die Anzahl der Datenbankabfragen nicht reduziert
wurde. Dies ist dadurch zu erklären, dass im \ac{EJB} die Provider gelagert werden, die über Dependency Injection
den Controller bereitgestellt werden. Die Objekt selbst werden nicht im \ac{EJB}"=Cache hinterlegt.
dem Controller bereitgestellt werden. Die Objekte selbst werden nicht im \ac{EJB}"=Cache hinterlegt.
% document, documentaddresseeperson, first/last, documentcoauthorperson, count und documentfacsimile
\begin{table}[h!]
@ -324,7 +323,7 @@ den Controller bereitgestellt werden. Die Objekt selbst werden nicht im \ac{EJB}
\section{Abfragen JPQL}
\label{sec:performance-investigation-application:query-jpql}
Für die \ac{JPQL} wird ein \ac{SQL} ähnlicher Syntax verwendet um die Abfragen an die Datenbank durchzuführen. Für die
Für die \ac{JPQL} wird ein \ac{SQL} ähnlicher Syntax verwendet, um die Abfragen an die Datenbank durchzuführen. Für die
Dokumentenliste wird der Code aus \autoref{lst:jpql-document-list-jpql} verwendet. Die Namen mit vorangestellten
Doppelpunkt sind Übergabevariablen.
@ -369,25 +368,25 @@ gesetzt, welcher viel zu gering ist. Als weiterer Test wurde der Wert auf die an
Ebenso bringt der Hint \texttt{openjpa.""FetchPlan.""ReadLockMode} auch keinen Unterschied bei der Geschwindigkeit.
Dies ist dadurch erklärbar, dass im Standard bei einer reinen Selektion eine Lesesperre aktiv sein muss.
Bei \texttt{openjpa.""FetchPlan.""Isolation} wird gesteuert, auf welche Sperren beim Laden geachtet wird. Damit könnte
man lediglich Schreibsperren umgehen, und würde damit die Anfrage nicht mehr blockieren lassen, jedoch führt es unweigerlich
man lediglich Schreibsperren umgehen und würde damit die Anfrage nicht mehr blockieren lassen, jedoch führt es unweigerlich
zu sogenannten >>Dirty"=Reads<<, wodurch die Ausgabe verfälscht werden könnte. Daher ist diese Einstellung
mit Vorsicht zu verwenden.
Mit dem Hint \texttt{openjpa.""FetchPlan.""EagerFetchMode} wird definiert, wie zusammengehörige Objekte abgefragt werden.
Bei dem Wert \textit{none} werden nur die Basis"=Daten abgefragt und jedes weitere Objekt wird in einem eigenen
Statement abgefragt. Mit \textit{join} wird definiert, dass abhängige Objekte die als >>to-one<<"=Relation
Statement abgefragt. Mit \textit{join} wird definiert, dass abhängige Objekte, die als >>to-one<<"=Relation
definiert sind, in der Abfrage über einen Join verknüpft und damit direkt mitgeladen werden. Bei reinen
>>to-one<<"=Relation funktioniert das Rekursiv und spart sich damit einige einzelne Abfragen.
Bei der Einstellung \textit{parallel} wird zwar für jede abhängige Objektdefinition eine Abfrage ausgeführt und
diese werden direkt auf die Hauptobjekte gefiltert und die Verknüpfung im OpenJPA"=Framework durchgeführt.
Somit muss in diesem Beispiel nicht für jedes Dokument eine einzelne Abfrage für die Koautoren durchgeführt werden,
es wird lediglich eine Abfrage für alle Dokumente welche ermittelt wurden abgesetzt. Technisch gesehen wird die gleiche
es wird lediglich eine Abfrage für alle Dokumente, welche ermittelt wurden, abgesetzt. Technisch gesehen wird die gleiche
WHERE"=Abfrage nochmal durchgeführt und um die JOINS ergänzt, um die Daten der Unterobjekte zu ermitteln.
Mit dem Hint \texttt{openjpa.""FetchPlan.""SubclassFetchMode} ist die Konfiguration für Unterklassen definiert. Die
Möglichkeiten entsprechen der vom \texttt{openjpa.""FetchPlan.""EagerFetchMode}.
Beim Umstellen der 2 Hints auf \textit{parallel} wird die Bearbeitungszeit fast halbiert und Anzahl der Datenbankaufrufe
wurde fast geviertelt. Dies zeigt, dass die einzelnen Aufrufe je Dokument aufwendiger sind, als eine komplette Abfrage
wurde fast geviertelt. Dies zeigt, dass die einzelnen Aufrufe je Dokument aufwendiger sind als eine komplette Abfrage
der abhängigen Daten und das zusammensetzen in der OpenJPA-Schicht.
Der letzte Hint \texttt{openjpa.""FetchPlan.""MaxFetchDepth} schränkt die rekursive Tiefe ein, für die abhängige
@ -396,9 +395,9 @@ Objekte mitgeladen werden. Lediglich auf Grund fehlender Datenbestände wird die
\section{Abfragen Criteria API}
\label{sec:performance-investigation-application:query-criteria-api}
Für die Criteria API wird die Abfrage nicht in einem SQL-Dialekt beschreiben, hierbei werden über Attribute die
Für die Criteria API wird die Abfrage nicht in einem \ac{SQL}"=Dialekt beschreiben, hierbei werden über Attribute die
Verlinkung zur Datenbank durchgeführt. An der Klasse selbst wird der Tabellenname definiert und an den Attributen die
Spaltennamen. Um die Anfrage durchzuführen muss nun nur noch die Datenklasse angegeben und mit den Parametern
Spaltennamen. Um die Anfrage durchzuführen, muss nun nur noch die Datenklasse angegeben und mit den Parametern
versorgt werden, wie es in \autoref{lst:criteria-api} gezeigt wird.
\begin{lstlisting}[language=Java,caption={Criteria API Dokumentenliste},label=lst:criteria-api]
@ -465,18 +464,18 @@ Geschwindigkeit optimiert.
\label{sec:performance-investigation-application:materialized-views}
\textit{Materialized Views} sind Sichten in der Datenbank, die beim Erstellen der Sicht den aktuellen Zustand ermitteln
und zwischenspeichern. Somit wird beim Zugriff auf diese Sichten, nicht die hinterlegte Abfrage ausgeführt, sondern auf
und zwischenspeichern. Somit wird beim Zugriff auf diese Sichten nicht die hinterlegte Abfrage ausgeführt, sondern auf
die gespeicherten Daten zugegriffen. Dies ist gerade bei vielen Joins von Vorteil. Zusätzlich können auf solchen
Sichten auch Indexe erstellt werden, um noch effektiver die Abfragen bearbeiten zu können.
Der größte Nachteil dieser Sichten ist, dass sie zyklisch oder bei Datenänderungen aktualisiert werden müssen, sonst
läuft der Datenbestand der Sicht und der zugrundeliegenden Abfrage auseinander. Da die Hauptarbeiten auf der Webseite
die Abfrage der Daten ist, und nicht das Editieren, kann dieser Nachteil bei entsprechender Optimierung ignoriert werden.
die Abfrage der Daten ist und nicht das Editieren, kann dieser Nachteil bei entsprechender Optimierung ignoriert werden.
In diesem Test wurde die aktuelle Implementierung aus dem Wedekind"=Projekt der \textit{Materialized View} inklusive
der Trigger und der \textit{SearchDocument}"=Klasse übernommen \citep{Dokument53:online}. Wie in
\autoref{lst:sql-materialized-view} zu sehen, wurden zur Standard"=Abfrage, die sonst zusätzlichen Abfragen als
direkte Sub"=Selects mit integriert. Der Datenbestand dieser Sub"=Selects, wird im Json"=Format angegeben, damit bei
\autoref{lst:sql-materialized-view} zu sehen, wurden zur Standard"=Abfrage die sonst zusätzlichen Abfragen als
direkte Sub"=Selects mit integriert. Der Datenbestand dieser Sub"=Selects wird im Json"=Format angegeben, damit bei
den Koautoren und den Adressen mehrere Datensätze in einer Zeile zurückgegeben werden können. Ohne diese Technik würde
sich die Anzahl der Dokumente vervielfachen.
@ -618,10 +617,10 @@ der Speicheranstieg weniger stark aus. Die Verbesserung der Aufrufzeiten lässt
nur noch vier statt der sechs an die Datenbank gestellt werden, da die Einzelabfragen für die Adressen der
Personen und der Koautoren komplett entfallen.
Nach einer weiteren Untersuchung des Quellcodes konnte man festellen, dass bei jeder Anfrage die gleiche Bedingung
benötigt wurden. Da die Sicht nun explizit für diese Anfrage geschaffen wurde, wurde die Bedingungen nun direkt in die
Nach einer weiteren Untersuchung des Quellcodes wird festgestellt, dass bei jeder Anfrage die gleiche Bedingungen
benötigt werden. Da die Sicht nun explizit für diese Anfrage geschaffen ist, werden die Bedingungen nun direkt in die
Sicht mit integriert. Dies bedeutet eine Erweiterung der Sicht aus \autoref{lst:sql-materialized-view} um
\autoref{lst:sql-materialized-view-ext} und das Entfernen der Parameter aus dem SQL"=Anfragen im Java"=Code.
\autoref{lst:sql-materialized-view-ext} und das Entfernen der Parameter aus dem \ac{SQL}"=Anfragen im Java"=Code.
\begin{lstlisting}[language=SQL,caption={SQL Materialized View Erweiterung},label=lst:sql-materialized-view-ext]
WHERE d.validuntil > NOW()
@ -654,9 +653,9 @@ zeigen nur minimale Unterschiede in den Zeiten, diese sind auf Messtoleranzen zu
Da bei der \textit{Materialized View} das Laden der Daten und das Wandeln in die Java"=Objekte getrennt programmiert
wurde, können hier eigene Zeitmessungen für die zwei Schritte eingebaut werden. Hierfür wird die Zeit vor dem
\texttt{map}"=Aufruf und der \texttt{map}"=Aufruf gemessen. Für die erste Messung, wurde vor der Datenbankabfrage ein
\texttt{map}"=Aufruf und der \texttt{map}"=Aufruf gemessen. Für die erste Messung wurde vor der Datenbankabfrage ein
\texttt{SearchDocument} Objekt erzeugt und dieses in jedem \texttt{map}"=Aufruf zurückgegeben. Mit diesem Aufbau wurde
die Zeit ermittelt, um die Daten aus der Datenbank zu laden und dieses Ergebnis einmalig zu durchlaufen ohne ein
die Zeit ermittelt, um die Daten aus der Datenbank zu laden und dieses Ergebnis einmalig zu durchlaufen, ohne ein
Objekt zu erstellen. Hierbei lagen die Zeiten bei circa 1 ms für das reine Laden der Daten und 3 ms
für den Aufruf der \texttt{map}"=Funktion. Sobald innerhalb der \texttt{map}"=Funktion pro Eintrag ein Objekt
erzeugt wird, ohne die Konvertierung der ermittelten Daten in das Objekt, steigt die Laufzeit bereits auf 54 ms.
@ -668,9 +667,9 @@ dieser Wert zu klein oder groß definiert ist, wird die Laufzeit verschlechtert.
Laufzeit der Datenbankanfrage auf circa 20 ms verlängert. Wenn der Wert zu gering gewählt ist, dann wird zwar die
Laufzeit der Datenbankanfrage minimal verkürzt, aber die \texttt{map}"=Funktion wird dadurch verlängert.
Das Aktivieren der Cache"=Optionen wie in \autoref{sec:performance-investigation-application:caching-openjpa} oder in
\autoref{sec:performance-investigation-application:cached-query} \todo{Umbruch} dargestellt, haben keine Auswirkung auf die Performance.
Dies ist dadurch erklärbar, das keine Objekte durch das OpenJPA"=Framework erstellt werden, sondern erst in der
Das Aktivieren der Cache"=Optionen wie in \autoref{sec:performance-investigation-application:caching-openjpa} oder in %TODO schreibt in den Rand
\autoref{sec:performance-investigation-application:cached-query} dargestellt, haben keine Auswirkung auf die Performance.
Dies ist dadurch erklärbar, dass keine Objekte durch das OpenJPA"=Framework erstellt werden, sondern erst in der
\texttt{map}"=Funktion des eigenen Codes und daher wird der Cache nicht genutzt.
Wie schon ermittelt, benötigt das Erstellen der Objekte den Großteil der Zeit für die Datenermittlung. Auf Grund dessen
@ -679,9 +678,9 @@ wurde die übernommene \texttt{SearchDocument}"=Klasse abermals genauer betracht
Seite nochmals aufgerufen. Durch diese Umstellung fällt die Laufzeit der Datenermittlung auf circa 4 ms ab. Nun muss
noch überprüft werden, welche Zeit nun der Client zum parsen der \textit{Json}"=Daten benötigt. Hierfür werden die
Daten in einem versteckten \texttt{span}"=Element hinterlegt, wie es im \autoref{lst:jsf-datatable-json} zu sehen ist.
Die hinterlegte \textit{CSS}"=Klasse ist zum auffinden der Elemente für den späteren Javascript. Das
Die hinterlegte \textit{\acs{CSS}}"=Klasse ist zum Auffinden der Elemente für den späteren Javascript. Das
\textit{ajax}"=Element im Beispiel ist notwendig, damit bei einem Seitenwechsel die gleiche Interpreter"=Funktion für
die \textit{Json}"=Daten aufgerufen wird, wie beim laden der Webseite.
die \textit{Json}"=Daten aufgerufen wird, wie beim Laden der Webseite.
\begin{lstlisting}[language=xml,caption={DataTable mit Json},label=lst:jsf-datatable-json]
<p:ajax event="page" oncomplete="convertJsonData()"/>
@ -696,9 +695,9 @@ die \textit{Json}"=Daten aufgerufen wird, wie beim laden der Webseite.
</p:column>
\end{lstlisting}
Die Interpreter"=Funktion, welche in JavaScript geschrieben ist, wird benötigt um die übertragenen
Die Interpreter"=Funktion, welche in JavaScript geschrieben ist, wird benötigt, um die übertragenen
\textit{Json}"=Daten in eine darstellbare Form zu bringen. Die Funktion aus dem \autoref{lst:jsf-datatable-json-convert}
ermittelt erst alle versteckten Elemente, deserialisiert den Inhalt und erstellt neue \textit{HTML}"=Elemente mit dem
ermittelt erst alle versteckten Elemente, deserialisiert den Inhalt und erstellt neue \textit{\ac{HTML}}"=Elemente mit dem
darzustellenden Inhalt. Zusätzlich wird noch eine Zeitmessung eingebaut, um die Laufzeit am Client für das Rendern
in der Konsole anzuzeigen. Die Funktion wird nun direkt nach dem die Webseite fertig geladen wurde aufgerufen.
@ -752,7 +751,7 @@ ist geringer als die reine Serverlösung und erzeugt gleichzeit weniger Last am
\label{sec:performance-investigation-application:optimizing-query}
Für die Optimierung der Abfragen werden diese zuerst mit \texttt{EXPLAIN}, wie in \autoref{lst:explain-diagnostic}
dargestellt, untersucht. Für die einfachere Diagnose, wird der erstellte Plan mit Hilfe von
dargestellt, untersucht. Für die einfachere Diagnose wird der erstellte Plan mit Hilfe von
\textit{Postgres Explain Visualizer 2} (\url{https://github.com/dalibo/pev2}) visualisiert.
\begin{lstlisting}[language=SQL,caption={Explain für Diagnose},label=lst:explain-diagnostic]
@ -789,10 +788,10 @@ Knoten, dass die Menge der Datensätze enorm hoch ist und diese sich bis zum obe
bedeutet, dass die Einschränkung des Datenbestandes erst am Ende der Abfrage durchgeführt wird und diesbezüglich die
Dauer der Abfrage linear mit den Inhalt der \textit{document}"=Tabelle zusammenhängt. Des Weiteren wird für keine
Tabelle ein \textit{Index Scan} verwendet, sondern immer mit einem \textit{Seq Scan} gearbeitet, da durch das Ermitteln
des kompletten Datenbestandes der Optimizer entscheidet, ob der komplette Scan der Tabelle kostengünstiger ist, als
des kompletten Datenbestandes der Optimizer entscheidet, ob der komplette Scan der Tabelle kostengünstiger ist als
die Verwendung eines der vorhandenen Indexe. Dies kann durch den Befehl \lstinline[language=SQL]|SET enable_seqscan = off|
sehr einfach verifiziert werden. Damit wird die Verwendung von \textit{Seq Scan} deaktiviert und es wird anschließend ein
\textit{Index Scan} verwendet. Wenn man nun beide Pläne vergleicht sieht man die Erhöhung der Kosten bei der Verwendung
\textit{Index Scan} verwendet. Wenn man nun beide Pläne vergleicht, sieht man die Erhöhung der Kosten bei der Verwendung
von \textit{Index Scan}.
Die beste Optimierung hierbei ist, die Menge der Datensätze so früh wie möglich einzuschränken. Da die Verwendung von

View file

@ -7,11 +7,11 @@ Nun werden die durchgeführten Anpassungen anhand ihre Effektivität betrachtet
diese eine Optimierung darstellen. Weiterhin werden die Nachteile der Anpassungen überprüft und und bei der Betrachtung
der Effektivität mit beachtet.
Es wurden die Konfigurationen der Caches von OpenJPA, JPA und EJB aktiviert und deren Auswirkung betrachtet. Bei den
Caches, bei denen eine Größe angebbar ist, wurde zusätzlich mit der Anzahl variiert, um zu ermitteln in welchem Umfang
Es wurden die Konfigurationen der Caches von OpenJPA, \ac{JPA} und \ac{EJB} aktiviert und deren Auswirkung betrachtet. Bei den
Caches, bei denen eine Größe angebbar ist, wurde zusätzlich mit der Anzahl variiert, um zu ermitteln, in welchem Umfang
sich diese auswirkt. Des Weiteren wird die Art der Programmierung für die Abfragen betrachtet, ob signifikante
Unterschiede in der Performance und der Abarbeitung erkennbar sind. Als weiteren Punkt werden die Abfragen an die
Datenbank untersucht, um zu ermitteln ob diese durch Umstellung verbessert werden können. Abschließend werden die
Datenbank untersucht, um zu ermitteln, ob diese durch Umstellung verbessert werden können. Abschließend werden die
\textit{Materialized View} verwendet, um zu ermitteln, ob durch einen vorverdichteten und aufbereiteten Datenbestand
die Abfragen beschleunigt werden können.
@ -19,13 +19,13 @@ die Abfragen beschleunigt werden können.
\label{sec:evaluation:user-survey}
Zusätzlich war noch eine Befragung unter den Benutzer und den Entwicklern geplant. Auf Grund dessen, dass nur fünf
Personen zur Verfügung stehen ist dies nicht zielführend. Daher ist die einzig sinnvolle Alternative, welche gewählt
Personen zur Verfügung stehen, ist dies nicht zielführend. Daher ist die einzig sinnvolle Alternative, welche gewählt
wurde, ein rein technischer Ansatz.
\section{Umgestalten der Datenbanktabellen}
\label{sec:evaluation:new-table}
Hierfür wurde die aktuelle Datenstruktur untersucht um zu überprüfen, ob eine Umgestaltung der Tabelle einen Verbesserung
Hierfür wurde die aktuelle Datenstruktur untersucht, um zu überprüfen, ob eine Umgestaltung der Tabelle eine Verbesserung
bringen würde. Die typische Optimierung ist die Normalisierung der Tabellenstruktur. Die Tabellenstruktur ist aktuell
schon normalisiert, daher kann hier nichts weiter optimiert werden.
@ -37,7 +37,7 @@ Serverseite zusammenzuführen.
\section{Statische Webseiten}
\label{sec:evaluation:static-website}
Eine Umstellung der Dokumentenliste in statische Webseite, würde die Zugriffszeiten sehr verkürzen. Darüber hinaus
Eine Umstellung der Dokumentenliste in statische Webseite würde die Zugriffszeiten sehr verkürzen. Darüber hinaus
funktionieren in statischen Webseiten aber keine Suchen oder Sortierungen. Die Sortierung könnte durch das Erstellen
von statischen Seiten aller Möglichkeiten der Sortierung emuliert werden, diese würde den notwendigen Speicherbedarf der
Webseite vervielfachen. Für die Suchanfragen ist dies nicht mehr möglich, da nicht alle Suchanfragen vorher definiert
@ -63,10 +63,10 @@ die notwendige Rechenleistung fehlt, um die Webseite in annehmbarer Zeit darzust
\section{Serverseitige Paginierung}
\label{sec:evaluation:server-side-paging}
Die Aufteilung eines großen Datenbestandes in mehrere einzelne Seiten, ist eine der wenige Optimierungsmöglichkeiten in
der JSF"=Ebene. Dieser Einbau optimiert direkt an mehreren Stellen, dazu gehört die kleinere Datenmenge die vom
Datenbankserver geladen wird. Ebenso wird entsprechend weniger Zeit benötigt um die View zu erstellen,
gleichzeitig wir die übertragene Datenmenge an den Client reduziert. Dadurch benötigt die Seite auf dem Client weniger
Die Aufteilung eines großen Datenbestandes in mehrere einzelne Seiten ist eine der wenigen Optimierungsmöglichkeiten in
der \ac{JSF}"=Ebene. Dieser Einbau optimiert direkt an mehreren Stellen, dazu gehört die kleinere Datenmenge, die vom
Datenbankserver geladen wird. Ebenso wird entsprechend weniger Zeit benötigt, um die View zu erstellen,
gleichzeitig wird die übertragene Datenmenge an den Client reduziert. Dadurch benötigt die Seite auf dem Client weniger
Zeit zum rendern.
Da das Paging für den Fall der Dokumentenliste implementiert ist, gibt es hier keine weiteren offensichtliche
@ -115,30 +115,30 @@ Dadurch ist dieser Cache für eine Performance"=Verbesserung in dem Fall der Dok
Mit dem Ehcache konnte eine Verbesserung in der Performance erzielt werden. Im Vergleich zum Cache von OpenJPA sind
die Verbesserung sehr ähnlich. Die Standardwerte dieses Caches sind gut vordefiniert, es wird für den aktuellen Fall
keine Anpassung benötigt um eine gute Performance zu bekommen. Hierbei ist natürlich das gleiche Problem wie in anderen
Caches, dass beim Erreichen der Grenzen, alte Objekte entfernt werden müssen.
keine Anpassung benötigt, um eine gute Performance zu bekommen. Hierbei ist natürlich das gleiche Problem wie in anderen
Caches, dass beim Erreichen der Grenzen alte Objekte entfernt werden müssen.
Nach aktueller Beobachtung scheint die Verwaltung im Ehcache effizienter gestaltet zu sein, als die des OpenJPA"=Caches.
Nach aktueller Beobachtung scheint die Verwaltung im Ehcache effizienter gestaltet zu sein als die des OpenJPA"=Caches.
Im Falle des Ehcache ist die interne Verwaltung auf mehrere Caches aufgebaut, dies ist daran zu sehen, dass in der
Standardkonfiguration jede Klasse ihren eigenen Cache besitzt. Diese können einzeln konfiguriert und diagnostiziert
werden, um diese genau auf die jeweiligen Bedürfnisse der Objekte anzupassen.
Im Falle der Verwendung des Caches, ist auch hier gut zu sehen, dass der Speicheranstieg bei der Verwendung des Caches
Im Falle der Verwendung des Caches ist auch hier gut zu sehen, dass der Speicheranstieg bei der Verwendung des Caches
sehr gering ist, dies deutet ebenfalls darauf hin, dass die Speicherproblematik beim Erstellen von Objekten innerhalb
des OpenJPA Framework liegen muss.
Durch die effizienter Verwendung des Speichers, ist der Ehcache die bessere Alternative zum OpenJPA"=Cache. Dieser ist
Durch die effizientere Verwendung des Speichers, ist der Ehcache die bessere Alternative zum OpenJPA"=Cache. Dieser ist
auch schon für kleinere Serverkonfigurationen gut verwendbar. Hierbei ist nur abzuwägen, mit welcher Größe der Cache
bereitgestellt werden kann, dies hängt direkt vom verfügbaren Arbeitsspeicher ab.
\section{Caching in EJB}
\label{sec:evaluation:ejb}
Bei der Erweiterung des EJB konnte keine Verbesserung in der Performance festgestellt werden. Der Grund hierfür ist, dass
im EJB"=Cache die Provider beinhaltet, aber keine Daten"=Objekte. Dadurch kann der Cache das Ermitteln der Objekte
Bei der Erweiterung des \ac{EJB} konnte keine Verbesserung in der Performance festgestellt werden. Der Grund hierfür ist, dass
der \ac{EJB}"=Cache die Provider beinhaltet, aber keine Daten"=Objekte. Dadurch kann der Cache das Ermitteln der Objekte
nicht optimieren.
Auf Grund dessen ist der EJB"=Cache nicht für eine Performance"=Verbesserung nutzbar.
Auf Grund dessen ist der \ac{EJB}"=Cache nicht für eine Performance"=Verbesserung nutzbar.
\section{Abfragen mit JPQL und Criteria API}
\label{sec:evaluation:jpal-capi}
@ -148,8 +148,8 @@ Abfragen kein Unterschied festgestellt werden. Die Abfragen der beiden Systeme s
identisch. Auch in der Übertragung der Daten aus der Datenbank in die Java"=Objekte konnte keine Unterschied in der
Art und Geschwindigkeit festgestellt werden.
Ebenfalls sind die Möglichkeiten über der Optimierung über Hints identisch. In beiden Fällen, haben die meisten Hints
keine nennenswerten Einfluss auf die Laufzeit der Abfragen und Übertragung in die Java"=Objekte. Das sinnvolle Setzen
Ebenfalls sind die Möglichkeiten über der Optimierung über Hints identisch. In beiden Fällen haben die meisten Hints
keinen nennenswerten Einfluss auf die Laufzeit der Abfragen und Übertragung in die Java"=Objekte. Das sinnvolle Setzen
von OptimizeResultCount, der FetchSize sowie der FetchBatchSize hilft dem Framework die Bearbeitung der Anfrage
effizient abzuarbeiten, konnte aber in den gemessenen Laufzeiten nicht verifiziert werden.
@ -170,12 +170,12 @@ Gleiches gilt dem Hint SubclassFetchMode, dieser steuert dimensionierte Abfragen
\section{Materialized View}
\label{sec:evaluation:materialized-view}
Die Idee der \textit{Materialized View} ist simple aber sehr effizient, gerade für einen Datenbestand welcher häufig gelesen
Die Idee der \textit{Materialized View} ist simple, aber sehr effizient, gerade für einen Datenbestand, welcher häufig gelesen
und selten verändert wird. Hierbei werden komplexe Abfragen einmalig ausgeführt und das Ergebnis intern
zwischengespeichert. Für alle weiteren Aufrufe, werden die Daten nun aus dem Zwischenspeicher gelesen und dem Aufrufer
zwischengespeichert. Für alle weiteren Aufrufe werden die Daten nun aus dem Zwischenspeicher gelesen und dem Aufrufer
zurückgegeben. Der größte Nachteil der \textit{Materialized View} ist, dass bei einer Änderung an den Quelldaten die
Sicht aktualisiert werden muss. Dieser Nachteil kommt in einer Briefedition nicht zum tragen, da in dieser nach dem die
Briefe einmalig eingepflegt wurden, nur noch selten Änderungen erfahren. Die Recherche zu dem Datenbestand wird die
Briefe einmalig eingepflegt wurden, nur noch selten Änderungen erfahren. Der Recherche zu dem Datenbestand wird die
meiste Zeit gewidmet.
Ein weiterer Nachteil der \textit{Materialized View} ist die doppelte Speicherung der Daten, da die Daten für die Sicht
@ -192,11 +192,11 @@ für jede Datenzeile einzeln durchgeführt wird.
Zusätzlich konnte dies nochmal beschleunigt werden, in dem das Parsen der \textit{Json}"=Daten vom Server auf den Client
verlagert wurde. Hiermit konnte ein Teil der Last vom Server genommen und die gesamte Ausführungszeit nochmals
optimiert werden. Die Wandlung der Daten in \textit{HTML}"=Objekte ist eine Kernkompetenz von JavaScript und damit auch bei
optimiert werden. Die Wandlung der Daten in \textit{\ac{HTML}}"=Objekte ist eine Kernkompetenz von JavaScript und damit auch bei
schwächeren Clients in kurzer Zeit durchführbar.
Als weiteren Punkt ist anzumerken, dass der Speicherbedarf des Webserver relativ konstant bleibt ohne das ein Cache
verwendet wird. Der größte Unterschied zur Standardimplementierung ist die Verwendung von eigenen Codes um die Objekte
Als weiteren Punkt ist anzumerken, dass der Speicherbedarf des Webserver relativ konstant bleibt, ohne dass ein Cache
verwendet wird. Der größte Unterschied zur Standardimplementierung ist die Verwendung von eigenen Codes, um die Objekte
zu erstellen und zu befüllen und es nicht durch das OpenJPA"=Framework durchführen zu lassen.
Dies legt den Schluss nahe, dass Probleme in der Speicherverwaltung der Objekte im OpenJPA"=Framework existieren.
@ -207,7 +207,7 @@ Ressourcennutzung verringert wird. Zum anderen wird die Ressourcennutzung des Se
Durch die doppelte Datenhaltung muss bei jeder Abfrage geprüft werden, ob die Nutzung der \textit{Materialized View} sinnvoll
ist oder direkt auf denormalisierte Daten umgestellt werden sollte, weil der zusätzliche benötigte Speicher größer als
die Quelle ist.
Im Gegensatz zu einer reinen Cache"=Lösung die die gleiche Optimierung besitzt, ist diese vorzuziehen, da in den
Im Gegensatz zu einer reinen Cache"=Lösung, die die gleiche Optimierung besitzt, ist diese vorzuziehen, da in den
meisten Fällen der Festplattenspeicher kostengünstiger als der Arbeitsspeicher ist. Zusätzlich ist der Cache begrenzt
und wirft alte Objekte heraus. Wenn dieser voll ist wird ein Zugriff auf diese entfernten Objekte
langsamer. Somit ist die Optimierung über die \textit{Materialized View} auf lange Zeit gesehen kostengünstiger und
@ -216,7 +216,7 @@ stabiler.
\section{Optimierung der Abfrage}
\label{sec:evaluation:optimize-query}
Die Abfragen die durch die OpenJPA an die Datenbank abgesetzt werden, sind meist durch ihre Einfachheit gut optimiert.
Die Abfragen, die durch die OpenJPA an die Datenbank abgesetzt werden, sind meist durch ihre Einfachheit gut optimiert.
Nur durch Sortierung oder Bedingungen können die Abfragen langsamer werden. Diese können durch entsprechende Indexe
gelöst werden. Bei größeren Abfragen mit mehreren Joins kann durch geschicktes umstellen die Performance verbessert
werden. Die Hauptabfrage der Dokumentenliste besteht aus mehreren Joins und diese wurde explizit untersucht.

View file

@ -3,8 +3,6 @@
\chapter{Zusammenfassung und Ausblick}
\label{ch:summary_and_outlook}
\mytodos{die 2 Untersektionen beibehalten?}
\section{Zusammenfassung}
\label{sec:Summary_and_outlook:results}
% In der Gegenwart schreiben, außer bei verweisen auf die Arbeit, dann in der Vergangenheit!
@ -17,28 +15,28 @@ vergleichbar bleiben und externe Einflussfaktoren minimiert werden.
Durch die Ausgangsmessungen war erkennbar, dass der größte Teil der Verarbeitungszeit im Bereitstellen der Entitäten
liegt. Die Messung der Abfragen auf der Datenbank wiederum konnte die hohe Verarbeitungszeit nicht bestätigen,
daher lag hier die Vermutung nahe, dass der Großteil der Zeit im ORM"=Mapper verloren geht.
daher lag hier die Vermutung nahe, dass der Großteil der Zeit im \ac{ORM} verloren geht.
Die Methode der Nutzerumfrage wurde nicht weiterverfolgt, da diese auf Grund zu wenigen Bedienern nicht zielführend war.
Bei der Untersuchung der Datenbank wurde festgestellt, dass die Struktur aktuell für die Anwendung optimal ist und
daher eine Restrukturierung keine Vorteile entstehen lässt. Die statische Webseite und die komplett Client basierte
Webseite wurden auf Grund von technischen Einschränkungen nicht weiterverfolgt.
Bei den Caches sind der Query"=Cache und der EJB"=Cache nicht für die Optimierung verwendbar. Der Query"=Cache wird
von OpenJPA nur verwendet, wenn die Abfragen keine Parameter besitzt, welche in der Dokumentliste verwendet werden
mussten. Im EJB"=Cache werden nicht die Objekt, sondern die Provider gespeichert, wodurch hier keine Auswirkung auf die
Bei den Caches sind der Query"=Cache und der \ac{EJB}"=Cache nicht für die Optimierung verwendbar. Der Query"=Cache wird
von OpenJPA nur verwendet, wenn die Abfrage keine Parameter besitzt, welche in der Dokumentliste verwendet werden
mussten. Im \ac{EJB}"=Cache werden nicht die Objekt, sondern die Provider gespeichert, wodurch hier keine Auswirkung auf die
Performance festgestellt werden konnte.
Anders sieht es bei dem OpenJPA"=Cache aus, dieser hat direkten Einfluss auf die Performance der Ermittlung der Daten
und Bereitstellung der dazugehörigen Java"=Objekte. Anhand der vorgegeben Cache"=Größe kann das Potential der
Optimierung eingestellt werden. Dies bedeutet, soweit der Cache groß genug ist um alle notwendigen Objekte zu
Optimierung eingestellt werden. Dies bedeutet, soweit der Cache groß genug ist, um alle notwendigen Objekte zu
speichern, sind die Verbesserungen gut sichtbar. Ab dem Zeitpunkt ab dem Objekte aus dem Cache entfernt werden müssen,
wird die Optimierung immer geringer.
Ein sehr ähnliches Verhalten konnte mit dem Ehcache festgestellt werden, nur dass bei diesem die Limitierungen höher
angesetzt sind und die Verwaltung des Caches im Gesamtsystem effizienter aufgebaut ist, als bei OpenJPA.
In beiden Fällen der Optimierung über die Nutzung eines Caches, konnte durch die Messungen in der Software und der
In beiden Fällen der Optimierung über die Nutzung eines Caches konnte durch die Messungen in der Software und der
Abfragen an der Datenbank nachgewiesen werden, dass nicht das Ermitteln der Daten die größte Zeit einnimmt, sondern
das Erstellen und Befüllen der Objekte in Java.
@ -46,23 +44,23 @@ Bei dem Vergleich der unterschiedlichen Abfragemethoden Criteria API und JPQL ko
Performance und Abarbeitung festgestellt werden. Bei beiden Methoden konnte nachgewiesen werden, dass die syntaktisch
gleichen Abfragen an die Datenbank gestellt wurden. Bei den Abfragen zur Dokumentenliste konnten in beiden Fällen
durch die Umstellung der Ermittlung der unterlagerten Daten durch Hints eine Optimierung erreicht werden. Die Umstellung
bezweckt das die unterlagerten Daten nicht einzeln für jede Zeile ermittelt wurden, sondern alle Daten auf einmal
bezweckt, dass die unterlagerten Daten nicht einzeln für jede Zeile ermittelt werden, sondern alle Daten auf einmal
geladen werden und die Zuordnung der Datensätze im OpenJPA"=Framework durchgeführt wird.
Mit der Übernahme der \textit{Materialized View} aus dem Wedekind"=Projekt konnte erstmalig ein gute Optimierung
beobachtet werden. Dies ist auf die einfachere Abfrage, die Reduzierung der Abfrage an den Datenbankserver und das
die Objekte im eigenen Code erstellt werden und nicht durch das OpenJPA"=Framework. Hierbei konnte noch nachgewiesen
beobachtet werden. Dies ist auf die einfachere Abfrage, die Reduzierung der Abfrage an den Datenbankserver und dass
die Objekte im eigenen Code erstellt werden zurückzuführen und nicht auf das OpenJPA"=Framework. Hierbei konnte noch nachgewiesen
werden, dass das Parsen der Json"=Daten, die die unterlagerten Objekte enthalten, den größten Teil der Zeit benötigen.
Auf Grund dessen wurde das Parsen der Json"=Daten auf den Client verschoben, was zu einem noch besseren Ergebnis führte.
Für die Optimierung der Abfragen wurde die Hauptabfrage betrachtet. Bei dieser konnte anhand der visuellen Darstellung
das Problem gut identifiziert werden. Durch die Verwendung einer \textit{Common Table Expression} wurde die Anzahl
der Datensätze direkt am Anfang auf die angefragte Menge reduziert, wodurch die Anzahl der zu betrachteten Datensätze
für die weiteren Verlinkungen enorm reduziert wurde. Somit konnte der Datenbankserver bei diesen Verlinkung auf Indexe
für die weiteren Verlinkungen enorm reduziert wurde. Somit konnte der Datenbankserver bei diesen Verlinkungen auf Indexe
zugreifen und damit die Abfragen zusätzlich beschleunigen.
Die Untersuchungen zeigen, dass mehrere Möglichkeiten zur Optimierung existierten, um die Zugriffe auf die
Briefeditionen zu beschleunigen und das das größte Optimierungspotential in dem ORM"=Mapper liegt. Welche der
Briefeditionen zu beschleunigen und das das größte Optimierungspotential in dem \ac{ORM} liegt. Welche der
Optimierungen verwendet werden, liegt an der Komplexität der Abfrage und der bereitgestellten Ressourcen
des Servers.
@ -74,11 +72,11 @@ Möglichkeiten für eine Optimierungen zulassen. Einzig das Parsen von Json ist
Server durchführbar. Auf diese Weise könnten zusätzlich die Ressourcen am Server reduziert werden beziehungsweise mit
gleichen Ressourcen mehr Anfragen als bisher beantwortet werden.
Die größten Optimierungspotentiale können durch Umstellung der Abfragen und der Optimierung des ORM"=Mappers umgesetzt
werden. Bei den Umstellungen der Abfragen ist größte Stärke, wenn die Anzahl der Abfragen drastisch reduziert werden
Die größten Optimierungspotentiale können durch Umstellung der Abfragen und der Optimierung des \ac{ORM} umgesetzt
werden. Bei den Umstellungen der Abfragen ist die größte Stärke, wenn die Anzahl der Abfragen drastisch reduziert werden
könnte.
Dadurch zeigt sich, dass die Untersuchung auf Ebene der ORM"=Mapper noch nicht abgeschlossen ist. Weitere Untersuchungen
nach anderen ORM"=Mapper könnten wie in \ref{sec:evaluation:materialized-view} angedeutet das Speicherproblem lösen,
Dadurch zeigt sich, dass die Untersuchung auf Ebene der \ac{ORM} noch nicht abgeschlossen ist. Weitere Untersuchungen
von anderen \ac{ORM} könnten wie in \ref{sec:evaluation:materialized-view} angedeutet das Speicherproblem lösen,
sowie eine generelle Optimierung der Webseite zur Folge haben. Eine eigenständige Implementierung eines einfachen
ORM"=Mapper wäre auch in Betracht zu ziehen, solange sich die Komplexität der Daten"=Struktur nicht erhöht.
\ac{ORM} wäre auch in Betracht zu ziehen, solange sich die Komplexität der Daten"=Struktur nicht erhöht.

View file

@ -4,8 +4,8 @@
\begin{otherlanguage}{american}
\pdfbookmark[0]{Abstract}{Abstract}
\chapter*{Abstract}
The Letter Edition of the Wedekind Project makes Frank Wedekind's correspondence available as an online
full"=text database in order to focus research on Frank Wedekind. In order to increase the acceptance of the
The Letter Edition of the Wedekind Project makes the correspondence from Frank Wedekind available as an online
full text database in order to focus research on Frank Wedekind. In order to increase the acceptance of the
website so that more researchers can deal with the subject, the response time for inquiries is to be reduced.
This paper looks at the different layers of the application and the respective optimization options. A purely

View file

@ -31,6 +31,7 @@
\acro{SQL}{Structured Query Language}
\acro{JVM}{Java Virtual Machine}
\acro{JSON}{JavaScript Object Notation}
\acro{DBMS}{Database Management System}
\end{acronym}
\cleardoublepage

Binary file not shown.