Daily CheckIn
This commit is contained in:
parent
ebec44cdee
commit
1f34a0a382
13 changed files with 161 additions and 168 deletions
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
@ -22,6 +22,7 @@
|
|||
"Planerstatistiken",
|
||||
"Plantypen",
|
||||
"SFSB",
|
||||
"skriptbasierte",
|
||||
"tabellenähnlichen",
|
||||
"unterlagerte",
|
||||
"unterlagerten",
|
||||
|
|
|
@ -14,7 +14,7 @@ Durch die nummerierten Präfixe können im Nachgang über die \textit{pgBadger}"
|
|||
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
|
||||
niedriges Level fällt, danach kann das Skript für die Messungen gerufen werden.
|
||||
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}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
Für die Protokollierung der Abläufe im \ac{JSF} werden zwei Klassen benötigt. Über die Factory \ref{lst:logger_factory},
|
||||
wird die Wrapper"=Klasse in die Bearbeitungsschicht eingeschleust. Diese Wrapper"=Klasse \ref{lst:logger} beinhaltet
|
||||
dann die eigentliche Performance-Messung, inklusive der Ausgabe in die Log"=Datei des \textit{Glassfish}"=Servers.
|
||||
dann die eigentliche Performance"=Messung, inklusive der Ausgabe in die Log"=Datei des \textit{Glassfish}"=Servers.
|
||||
Zusätzlich muss in der Konfiguration \texttt{faces-config.xml} noch angepasst werden, wie in
|
||||
\ref{lst:logger_factory_activate}, um die Factory durch das System aufrufen zu lassen.
|
||||
|
||||
|
|
|
@ -3,12 +3,10 @@
|
|||
\chapter{Einleitung}
|
||||
\label{ch:intro}
|
||||
|
||||
\mytodos{Verena: Performance"=Verbesserung oder Perfromanceverbesserung?}
|
||||
|
||||
Die Akzeptanz und damit die Verwendung einer Software hängt von verschiedenen Kriterien
|
||||
ab. Hierbei ist neben der Stabilität und der Fehlerfreiheit die Performance beziehungsweise
|
||||
die Reaktionszeit der Software ein sehr wichtiges Kriterium. Hierfür muss sichergestellt
|
||||
werden, dass die Anwendung immer in kurzer Zeit reagiert oder entsprechende Anzeigen dargestellt werden
|
||||
werden, dass die Anwendung immer in kurzer Zeit reagiert oder entsprechende Anzeigen dargestellt werden,
|
||||
um eine längere Bearbeitung anzuzeigen.
|
||||
|
||||
%\section{Motivation}
|
||||
|
@ -53,48 +51,47 @@ eingesehen werden kann. Hierbei wurden sämtliche bislang bekannte Korrespondenz
|
|||
Briefe selbst werden im etablierten TEI"=Format gespeichert und über einen WYSIWYG"=Editor von den Editoren und
|
||||
Editorinnen eingegeben.
|
||||
|
||||
Das Projekt wurde anhand von bekannten und etablierten Entwurfsmustern umgesetzt um eine modulare und unabhängige
|
||||
Das Projekt wurde anhand von bekannten und etablierten Entwurfsmustern umgesetzt, um eine modulare und unabhängige
|
||||
Architektur zu gewährleisten, damit dies für weitere digitale Briefeditionen genutzt werden kann.
|
||||
|
||||
\section{Ziel der Arbeit}
|
||||
\label{sec:intro:goal}
|
||||
|
||||
Die aktuelle Umsetzung beinhaltet die bisher definierten Anforderungen vollständig, darunter fallen die
|
||||
Recherchemöglichkeiten, sowie auch die Eingabe und die Verarbeitung der Briefe. Ein größeres Problem hierbei ist die
|
||||
Recherchemöglichkeiten sowie auch die Eingabe und die Verarbeitung der Briefe. Ein größeres Problem hierbei ist die
|
||||
Performance der Oberfläche. Auf Grund der langen Abfragedauer des Datenbestandes leidet die Akzeptanz der Anwendung.
|
||||
|
||||
Das Ziel dieser Arbeit ist es, die Abfragedauer zu verringern, wodurch die Performance der Oberfläche signifikant
|
||||
verbessert wird. \mytodos{verena}
|
||||
verbessert wird.
|
||||
|
||||
\section{Gliederung}
|
||||
\label{sec:intro:structure}
|
||||
|
||||
Zu Beginn der Arbeit werden im \autoref{ch:basics} die Struktur und der grundsätzliche Aufbau der Anwendung
|
||||
Zu Beginn der Arbeit werden in \autoref{ch:basics} die Struktur und der grundsätzliche Aufbau der Anwendung
|
||||
erklärt. Hierbei wird aufgezeigt an welchen Stellen es immer wieder zu Unstimmigkeiten kommen kann und wie diese zu
|
||||
überprüfen sind.
|
||||
|
||||
Nachfolgend werden im \autoref{ch:concept} die Konzepte vorgestellt, die die Stellen ermitteln, die eine schlechte
|
||||
Nachfolgend werden in \autoref{ch:concept} die Konzepte vorgestellt, die die Stellen ermitteln, welche eine schlechte
|
||||
Performance aufweisen und optimiert werden sollen.
|
||||
Hierzu gehören zum einen die Einstellungen der verwendeten Software, und zum anderen der Aufbau und die verwendeten
|
||||
Techniken in der Anwendung. Diese Techniken werden im weiteren Verlauf nochmal überprüft, ob eine alternative Lösung
|
||||
einen performantere Umsetzung bringen kann.
|
||||
|
||||
Bei den Performance"=Untersuchungen im \autoref{ch:performance-checking} werden nun die Konzepte angewandt, um
|
||||
Bei den Performance"=Untersuchungen in \autoref{ch:performance-checking} werden nun die Konzepte angewandt, um
|
||||
die Umgebung selbst zu untersuchen und die dort bekannten Probleme zu ermitteln. Diese werden direkt bewertet, unter den
|
||||
Gesichtspunkten, ob eine Optimierung an dieser Stelle sinnvoll ist oder ob der Arbeitsaufwand dafür zu aufwendig ist.
|
||||
Zusätzlich werden noch die Vorbereitungen und die angepassten Konfigurationen für die nachfolgenden
|
||||
Performance"=Untersuchungen der Anwendung aufzeigt.
|
||||
|
||||
Zuerst wird im \autoref{ch:performance-investigation-application} die Ausgangsmessung durchgeführt, hierbei werden
|
||||
Zuerst wird in \autoref{ch:performance-investigation-application} die Ausgangsmessung durchgeführt, hierbei werden
|
||||
alle bekannten Caches deaktiviert und eine Messung durchgeführt.
|
||||
Dann werden Schicht für Schicht die Optimierungsmöglichkeiten aufgezeigt, umgesetzt und erneut gemessen. Diese Messung
|
||||
wird mit der Ausgangsmessung verglichen und bewertet.
|
||||
|
||||
Nach der Optimierung kommt nun die Evaluierung im \autoref{ch:evaluation}. Hier werden die verschiedenen Optimierungen
|
||||
Nach der Optimierung kommt nun die Evaluierung in \autoref{ch:evaluation}. Hier werden die verschiedenen Optimierungen
|
||||
begutachtet, in welchem Anwendungsfall die gewünschte Verbesserung in der Performance umgesetzt werden kann und welche
|
||||
für den vorliegenden Fall in der Praxis umsetzbar ist.
|
||||
|
||||
\todo{verena}
|
||||
Zum Abschluss im \autoref{ch:summary_and_outlook} \texthl{werden alle Optimierungen zusammengefasst und eine Abwägung}
|
||||
Zum Abschluss in \autoref{ch:summary_and_outlook} werden alle Optimierungen zusammengefasst und eine Abwägung
|
||||
getroffen, unter welchen Gesichtspunkten die Anpassungen eine sinnvolle Optimierung darstellen. Zusätzlich wird
|
||||
beschrieben wie ein weiteres Vorgehen durchgeführt werden kann.
|
||||
|
|
|
@ -8,11 +8,10 @@ dass jeder Wechsel einer Seite oder eine Suchanfrage als Web"=Request an den Ser
|
|||
geht durch mehrere Schichten des Server"=System bis die Antwort an den Client zurückgesendet wird, wie in
|
||||
\autoref{fig:webrequest} dargestellt.
|
||||
|
||||
\todo{die rede sein????}
|
||||
Es wird ab hier immer von einem \textit{Glassfish}"=Server die rede sein. In der Praxis wird ein \textit{Payara}"=Server
|
||||
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 die neuen 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. In dem weiteren Text
|
||||
bereitgestellt wird und neue 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.
|
||||
|
||||
Angefangen bei der Anfrage die über den Webbrowser an den Server gestellt wird und vom \textit{Glassfish}"=Server
|
||||
|
@ -25,9 +24,9 @@ Hier wird nun geprüft, ob die Daten aus dem \textit{OpenJPA Cache} direkt ermit
|
|||
an das unterlagerte Datenbankmanagementsystem \textit{PostgreSQL} weitergeleitet werden muss. Die ermittelten Daten vom
|
||||
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
|
||||
zu verringern. Um Anfragen die den Zugriff auf die Festplatte benötigen effizienter zu gestalten, bereiten die
|
||||
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
|
||||
zu verringern. Um Anfragen, die den Zugriff auf die Festplatte benötigen effizienter zu gestalten, bereiten die
|
||||
\textit{Services} die Datenstrukturen auf.
|
||||
|
||||
\begin{figure}[!ht]
|
||||
|
@ -75,7 +74,7 @@ zu verringern. Um Anfragen die den Zugriff auf die Festplatte benötigen effizie
|
|||
In den Java"=EE"=Anwendungen wird der \textit{Persistenzkontext} für die Anfragen vom \textit{Application"=Server}
|
||||
bereitgestellt. Hierfür werden \textit{Application"=Server} wie \textit{GlassFish} genutzt, um die Verwendung eines Pools
|
||||
von Datenbankverbindungen zu definieren \citep[68]{MüllerWehr2012}. Dadurch kann die Anzahl der Verbindungen geringer
|
||||
gehalten werden als die Anzahl der Benutzer die an der Anwendung arbeiten. Zusätzlich werden die Transaktionen über
|
||||
gehalten werden als die Anzahl der Benutzer, die an der Anwendung arbeiten. Zusätzlich werden die Transaktionen über
|
||||
\textit{\ac{SFSB}} gehandhabt, welche automatisch vor dem Aufruf erzeugt und danach wieder gelöscht
|
||||
werden. Dies birgt allerdings den Nachteil, dass der \textit{Persistenzkontext} sehr groß werden kann, wenn viele
|
||||
Entities in den \textit{Persistenzkontext} geladen werden. Da dies häufig zu Speicher"~ und damit Performance"=Problemen
|
||||
|
@ -90,7 +89,7 @@ Objekte einen von vier Zuständen ein \citep[57]{MüllerWehr2012}. Im Zustand \t
|
|||
aber noch nicht in den Cache überführt worden. Wenn diese in den Cache überführt worden sind, nehmen sie den Zustand
|
||||
\texttt{Verwaltet} ein. Ist das Objekt aus dem Cache und der Datenbank entfernt worden, nimmt es den Zustand
|
||||
\texttt{Gelöscht} an. \texttt{Losgelöst} ist der letzte Zustand, bei dem das Objekt aus dem Cache entfernt worden ist,
|
||||
aber nicht aus der Datenbank.
|
||||
aber noch in der Datenbank verbleibt.
|
||||
|
||||
Eine Menge von Objekten wird als \textit{Persistenzkontext} bezeichnet. Solange die Objekte dem
|
||||
\textit{Persistenzkontext} zugeordnet sind, also den Zustand \texttt{Verwaltet} besitzen, werden diese auf Änderungen
|
||||
|
@ -100,16 +99,15 @@ Eine Menge von Objekten wird als \textit{Persistenzkontext} bezeichnet. Solange
|
|||
\section{Glassfish - OpenJPA Cache}
|
||||
\label{sec:basics:ojpac}
|
||||
|
||||
\todo{... die Verwendung spricht... - das spricht umformen}
|
||||
Zusätzlich kann im \textit{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}.
|
||||
\texthl{Zu Beachten ist, dass die Daten im \textit{Second Level Cache} explizit über die Änderungen informiert werden
|
||||
müssen, weil sonst beim nächsten Aufruf veraltete Werte geliefert werden.} Ebenfalls benötigt ein Cache einen höheren Bedarf
|
||||
Zu Beachten ist, dass die Daten im \textit{Second Level Cache} explizit über die Änderungen informiert werden
|
||||
müssen, um zu verhindern, dass bei einem nachfolgenden Aufruf veraltete Werte zurückgegeben werden. Ebenfalls benötigt ein Cache einen höheren Bedarf
|
||||
an Arbeitsspeicher, in dem die Daten parallel zur Datenbank bereitgestellt werden, daher ist die Benutzung nur
|
||||
problemlos bei Entities möglich, auf welche meist lesend zugegriffen wird.
|
||||
|
||||
In der OpenJPA"=Erweiterung für den L2-Cache, wird in \textit{Objekt"=Cache} (in OpenJPA als \textit{DataCache}
|
||||
In der OpenJPA"=Erweiterung für den L2-Cache wird in \textit{Objekt"=Cache} (in OpenJPA als \textit{DataCache}
|
||||
bezeichnet) und \textit{Query"=Cache} unterschieden. Über die Funktionen \texttt{find()} und \texttt{refresh()} oder einer Query
|
||||
werden die geladenen Entities in den Cache gebracht. Davon ausgenommen sind \textit{Large Result Sets} (Abfragen die
|
||||
nicht alle Daten auf einmal laden), \texttt{Extent}"=Technologien und Queries, die einzelne Attribute von Entities
|
||||
|
@ -131,11 +129,11 @@ die Einstellungen an den Entities angepasst werden \citep{IbmOpenJPACaching2023}
|
|||
\label{sec:basics:memorybuffers}
|
||||
|
||||
Die Speicherverwaltung des PostgreSQL"=Servers muss für Produktivsysteme angepasst werden \citep[34-38]{Eisentraut2013}.
|
||||
Hierunter fallen die \texttt{shared\_buffers} die bei circa 10 bis 25 Prozent des verfügbaren Arbeitsspeichers liegen
|
||||
Hierunter fallen die \texttt{shared\_buffers}, die bei circa 10 bis 25 Prozent des verfügbaren Arbeitsspeichers liegen
|
||||
sollten. Mit dieser Einstellung wird das häufige Schreiben des Buffers durch Änderungen von Daten und Indexen auf die
|
||||
Festplatte reduziert.
|
||||
|
||||
Die Einstellung \texttt{temp\_buffers} definiert wie groß der Speicher für temporäre Tabellen pro
|
||||
Die Einstellung \texttt{temp\_buffers} definiert, wie groß der Speicher für temporäre Tabellen pro
|
||||
Verbindung maximal werden darf und sollte ebenfalls überprüft werden. Ein zu kleiner Wert bei großen temporären Tabellen
|
||||
führt zu einem signifikanten Leistungseinbruch, wenn die Tabellen nicht im Hauptspeicher, sondern in einer Datei
|
||||
ausgelagert werden.
|
||||
|
@ -156,7 +154,7 @@ durchgeführt werden, damit die Performance des Systems durch die Änderungen de
|
|||
\citep[75]{Eisentraut2013}. Hierfür gibt es den \texttt{VACUUM}"=Befehl, welcher entweder per Hand oder automatisch durch
|
||||
das Datenbanksystem ausgeführt werden soll. Für die automatische Ausführung kann der maximal verwendete Speicher über
|
||||
die Einstellung \texttt{autovacuum\_work\_mem} gesondert definiert werden \citep{PostgresPro:Chap20.4:2023}.
|
||||
Neben dem Aufräumen durch \texttt{VACUUM}, sollten auch die Planerstatistiken mit \texttt{ANALYZE}
|
||||
Neben dem Aufräumen durch \texttt{VACUUM} sollten auch die Planerstatistiken mit \texttt{ANALYZE}
|
||||
\citep[83]{Eisentraut2013} aktuell gehalten werden, damit die Anfragen durch den Planer richtig optimiert werden können.
|
||||
Für beide Wartungsaufgaben gibt es den Autovacuum"=Dienst, dieser sollte aktiv und richtig konfiguriert sein.
|
||||
|
||||
|
@ -167,16 +165,16 @@ ermittelt werden.
|
|||
\section{PostgreSQL - Abfragen}
|
||||
\label{sec:basics:queries}
|
||||
|
||||
Für weitere Optimierungen werden anschließend die Anfragen einzeln überprüft. Hierfür ist es sinnvoll die
|
||||
Für weitere Optimierungen werden anschließend die Anfragen einzeln überprüft. Hierfür ist es sinnvoll, die
|
||||
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}.
|
||||
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 der wichtigsten Kennzeichen hierbei ist, ob die Zeilenschätzung akkurat war.
|
||||
Größere Abweichungen weißen häufig auf veraltete Statistiken hin.
|
||||
\citep[254]{Eisentraut2013}. Eine \todo{eine oder 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}.
|
||||
Zuerst wird unterschieden, ob es sich um eine \textit{Kurze} oder eine \textit{Lange} Abfrage handelt. Im Falle einer
|
||||
\textit{Kurzen} Abfrage, werden zuerst die Abfragekriterien überprüft. Sollte dies zu keiner Verbesserung führen,
|
||||
\textit{Kurzen} Abfrage werden zuerst die Abfragekriterien überprüft. Sollte dies zu keiner Verbesserung führen,
|
||||
werden die Indexe geprüft. Ist dies ebenso erfolglos, wird die Abfrage nochmals genauer analysiert und so
|
||||
umgestellt, dass die restriktivste Einschränkung zuerst zutrifft.
|
||||
Bei einer \textit{Langen} Abfrage soll überprüft werden, ob es sinnvoll ist, das Ergebnis in einer Tabelle zu
|
||||
|
@ -189,8 +187,8 @@ werden können, um die Abfragemenge zu verringern.
|
|||
Bei \textit{Langen} Abfragen ist die Abhandlung >>Optimizing Iceberg Queries with Complex Joins<<
|
||||
\citep{10.1145/3035918.3064053} ein zusätzlicher Ratgeber, um die Performance zu steigern.
|
||||
|
||||
Des Weiteren können über das Modul \texttt{pg\_stat\_statements} Statistiken der Aufrufe die an den Server gestellt
|
||||
Des Weiteren können über das Modul \texttt{pg\_stat\_statements} Statistiken der Aufrufe, die an den Server gestellt
|
||||
wurden, ermittelt werden \citep{PostgresF27:2023}. Hierbei können die am häufigsten Aufgerufenen und die Anfragen mit
|
||||
der längsten Ausführungszeit ermittelt werden. Ohne zu dem zusätzlichen Modul, können die Statistiken über die
|
||||
der längsten Ausführungszeit ermittelt werden. Ohne das zusätzliche Modul können die Statistiken über die
|
||||
Software \textit{pgBadger} erstellt werden. Dafür muss zusätzlich noch die Konfiguration des \textit{PostgreSQL}
|
||||
angepasst werden.
|
||||
|
|
|
@ -19,15 +19,15 @@ Hierunter fallen die Einstellungen für die \texttt{shared\_buffers}, der bei ei
|
|||
circa 25\% des Arbeitsspeicher besitzen sollte \cite{PostgresC20.4:2024}.
|
||||
|
||||
Bei der Einstellung \texttt{temp\_buffers} geht es um den Zwischenspeicher für jede Verbindung, die bei der Verwendung
|
||||
von temporären Tabellen verwendet wird. Dieser Wert sollte auf dem Standardwert von 8 MB belassen werden, lediglich bei
|
||||
der Verwendung von großen temporären Tabellen verändert werden.
|
||||
von temporären Tabellen verwendet wird. Dieser Wert sollte auf dem Standardwert von 8 MB belassen werden und lediglich
|
||||
bei der Verwendung von großen temporären Tabellen verändert werden.
|
||||
|
||||
Der Speicher, der für eine Abfrage verwendet werden darf, wird über die Konfiguration \texttt{work\_mem} gesteuert.
|
||||
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
|
||||
gesetzt werden. Mit dieser kann ermittelt, ob temporäre Dateien verwendet werden und deren Größe. Bei vielen kleineren
|
||||
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.
|
||||
|
||||
Für die Wartungsaufgaben wie VACUUM oder dem Erstellen von Indexen wird die Begrenzung über die Einstellung
|
||||
|
@ -38,14 +38,14 @@ 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. Da sonst der
|
||||
Server an seiner Leistungsgrenze arbeitet und dadurch es nicht mehr schafft die gestellten Anfragen schnell genug
|
||||
abzuarbeiten.
|
||||
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}
|
||||
|
||||
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,
|
||||
wodurch der aktuell nicht verwendete in die Page"=Datei ausgelagert wird. Hierdurch erhöhen sich die Zugriffszeiten auf
|
||||
diese Elemente drastisch.
|
||||
wodurch der aktuell nicht verwendete in die Page"=Datei ausgelagert wird. Zu beachten ist hierbei allerdings, dass sich
|
||||
die Zugriffszeiten auf die Elemente drastisch erhöhen.
|
||||
|
||||
Die Zugriffsgeschwindigkeit, die Zugriffszeit sowie die Warteschlange an der Festplatte zeigt deren Belastungsgrenze auf.
|
||||
In diesem Fall kann es mehrere Faktoren geben. Zum einem führt das Paging des Arbeitsspeicher zu erhöhten Zugriffen.
|
||||
|
@ -55,7 +55,7 @@ zwischengespeichert werden kann und daher diese Daten immer wieder direkt von de
|
|||
\section{Untersuchung der Anwendung}
|
||||
\label{sec:concept:softwarestructure}
|
||||
|
||||
Bei der Performance"=Untersuchung der Anwendung, wird sich im ersten Schritt auf die Dokumentenliste beschränkt. Anhand
|
||||
Bei der Performance"=Untersuchung der Anwendung wird sich im ersten Schritt auf die Dokumentenliste beschränkt. Anhand
|
||||
dieser können die Optimierungen getestet und überprüft werden. Im Nachgang können die daraus gewonnenen Kenntnisse auf
|
||||
die anderen Abfragen übertragen werden.
|
||||
|
||||
|
@ -72,7 +72,7 @@ Ort aufgehalten haben.
|
|||
|
||||
Da die Daten in der 3. Normalform in der Datenbank gespeichert werden, sind einige Relationen für die Abfragen
|
||||
notwendig. Dies wird durch die generische Abfrage in \autoref{lst:documentlist} gezeigt. Zusätzlich wird für jedes
|
||||
dargestellte Dokument eine zusätzliche Abfrage durchgeführt, die in \autoref{lst:documentlist_sub} zeigt, dass auch hier
|
||||
dargestellte Dokument eine zusätzliche Abfrage durchgeführt, wie in \autoref{lst:documentlist_sub} zeigt, dass auch hier
|
||||
weitere Relationen notwendig sind.
|
||||
|
||||
\includecode[SQL]{chapters/thesis/chapter03_documentlist.sql}{lst:documentlist}{Generische Abfrage der Dokumentenliste}
|
||||
|
@ -82,13 +82,13 @@ Nach aktuellem Stand beinhaltet die Datenbank circa 5400 Briefe, für die jeweil
|
|||
gespeichert werden. Diese Graphik-Dateien werden im TIFF-Format abgespeichert und benötigen zwischen 1 und 80 MB
|
||||
Speicherplatz. Dadurch kommt die Datenbank aktuell auf circa 3,8 GB.
|
||||
|
||||
Wie im \autoref{ch:basics} dargestellt, besteht die eigentliche Anwendung aus mehreren Schichten. Die
|
||||
PostgreSQL"=Schicht wurde schon im vorherigen Kapitel betrachtet. Daher gehen wir nun weiter nach oben in den Schichten
|
||||
vom Glassfish"=Server.
|
||||
Wie in \autoref{ch:basics} dargestellt, besteht die eigentliche Anwendung aus mehreren Schichten. Die
|
||||
PostgreSQL"=Schicht wurde schon im vorherigen Kapitel betrachtet. Daher werden nun die weiteren Schichten des
|
||||
Glassfish"=Server in aufsteigender Reihenfolge betrachtet.
|
||||
|
||||
Die OpenJPA Cache Schicht wird nun einzeln untersucht. Hierfür werden die zuerst die Cache"=Statistik für Object"=Cache
|
||||
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
|
||||
bereitgestellt, um die Daten Live vom Server verfolgen zu können. Zusätzlich werden die Webseite über ein Script
|
||||
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.
|
||||
|
||||
In der \ac{JPA} Schicht sind die Anzahl der Entitäten im Persistence Context zu beobachten. Die Anzahl der verschiedenen
|
||||
|
@ -112,27 +112,27 @@ Die Schicht \ac{EJB} besitzt keine Möglichkeit um eine sinnvolle Messung durchz
|
|||
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 einzuhängen, wird eine
|
||||
\textit{Factory} benötigt. In dieser werden die Zeiten zum Ermitteln der Daten, das Zusammensetzen und das Rendern
|
||||
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
|
||||
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 der größte Teil der Verzögerung auftritt.
|
||||
Skript ausgewertet. Somit ist es relativ leicht aufzuzeigen, an welcher Stelle die größte Verzögerung auftritt.
|
||||
|
||||
Die Abfragen werden ebenfalls untersucht und mit verschiedenen Methoden optimiert. Hierfür werden zum einen auf native
|
||||
SQL"=Anfragen umgestellt und die Ausführungszeiten überprüft. Ebenfalls werden die Abfragen durch Criteria API erzeugt
|
||||
SQL"=Anfragen umgestellt und die Ausführungszeiten überprüft. Zum anderen werden die Abfragen durch Criteria API erzeugt
|
||||
und dessen Ausführungszeit ermittelt.
|
||||
|
||||
Zusätzlich werden im SQL-Server Optimierungen vorgenommen, darunter zählen die \textit{Materialized View}, welche eine
|
||||
erweiterte Sicht ist. Neben der Abfrage der Daten beinhalteten diese auch noch vorberechneten Daten der Abfrage, womit
|
||||
erweiterte Sicht ist. Neben der Abfrage der Daten beinhalteten diese auch vorberechneten Daten der Abfrage, womit
|
||||
diese viel schneller abgefragt werden können. Zusätzlich werden die cached queries überprüft, ob diese eine Verbesserung
|
||||
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 alles Daten direkt in dem einen Aufruf bereitgestellt
|
||||
wird. In dem Skript werden zum einen die Laufzeiten der Webanfragen ermittelt und die kürzeste, die längste und die
|
||||
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
|
||||
\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.
|
||||
|
||||
Um die Netzwerklatenz ignorieren zu können, wird das Skript auf dem gleichen Computer aufgerufen, auf dem der Webserver
|
||||
gestartet wurde. Das zugehörige Script ist im \autoref{ap:timing} zu finden.
|
||||
gestartet wurde. Das zugehörige Script ist in \autoref{ap:timing} zu finden.
|
||||
|
|
|
@ -50,7 +50,7 @@ ausgewertet werden.
|
|||
Zusätzlich wird noch eine Implementierung der zugehörigen Factory"=Klasse \texttt{ViewDeclarationLanguageFactory}
|
||||
benötigt. Durch diese Factory"=Klasse wird der eigentlichen Wrapper mit der Performance-Messung in die Bearbeitungsschicht
|
||||
eingehängt. Diese Implementierung wird dann noch in der \texttt{faces-config.xml} eingetragen, wie das in
|
||||
\autoref{lst:activate-factory} gezeigt wird, damit die Factory durch das System aufgerufen wird.
|
||||
\autoref{lst:activate-factory} aufgezeigt wird, damit die Factory durch das System aufgerufen wird.
|
||||
|
||||
\begin{lstlisting}[language=xml,caption={Einbindung Factory},label=lst:activate-factory]
|
||||
<factory>
|
||||
|
@ -60,9 +60,9 @@ eingehängt. Diese Implementierung wird dann noch in der \texttt{faces-config.xm
|
|||
</factor>
|
||||
\end{lstlisting}
|
||||
|
||||
Der Quellcode der Klassen ist im \autoref{ap:jsf_performance_measure} zu finden.
|
||||
Der Quellcode der Klassen ist in \autoref{ap:jsf_performance_measure} zu finden.
|
||||
|
||||
Um die Abfragen im \textit{PostgreSQL} untersuchen zu können, ist es am leichtesten, wenn man die Konfiguration so
|
||||
Um die Abfragen im \textit{PostgreSQL} untersuchen zu können, ist es am einfachsten, wenn man die Konfiguration so
|
||||
anpasst, dass alle Abfragen mit entsprechenden Zeitmessungen in die Log"=Datei ausgegeben werden.
|
||||
Über die Einstellungen in \autoref{lst:postgresql_logfile} wird die Datei und das Format der Ausgabe definiert.
|
||||
|
||||
|
@ -104,7 +104,7 @@ log_timezone = 'Europe/Berlin'
|
|||
|
||||
Das Untersuchen der protokollierten Abfragen auf Performance Optimierungen ist ein weiterer Bestandteil dieser Arbeit.
|
||||
Das Schlüsselwort \texttt{EXPLAIN} ist im PostgreSQL vorhanden, um den Abfrageplan einer Abfrage zu ermitteln und
|
||||
darzustellen, um diesen zu untersuchen. Der Abfrageplan ist als Baum dargestellt, bei welchem die Knoten die
|
||||
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,
|
||||
wie Zwischenspeicherungen ersichtlich. Zu jeder Operation gibt es neben dem Typ noch zusätzliche Informationen, wie
|
||||
|
@ -122,25 +122,24 @@ EXPLAIN (ANALYZE, VERBOSE, BUFFERS, SUMMARY)
|
|||
select * from document;
|
||||
\end{lstlisting}
|
||||
|
||||
\todo{bei seq scan ... nochmal neu überlegen + Satz mit seigenden kosten fehlt}
|
||||
Die zwei bekanntesten Knotentypen sind \texttt{Seq Scan} und \texttt{Index Scan}. \texthl{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
|
||||
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
|
||||
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 Indexe. Diese sind aber mit Bedacht zu wählen, da bei
|
||||
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
|
||||
ein Index bei jeder Änderung der Daten zusätzliche Arbeit, da dieser entsprechend mit gepflegt werden muss und auch
|
||||
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
|
||||
Einschränkung durchführt. Zusätzlich muss die Art des Index definiert werden, welche davon abhängig ist, mit welcher
|
||||
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 die Ergebnisse in einer
|
||||
tabellenähnlichen Form abgespeichert. Somit sind die Zugriff auf diese Daten häufig performanter als die eigentliche Abfrage.
|
||||
\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
|
||||
als sinnvoll erachtet werden kann.
|
||||
|
||||
|
|
|
@ -25,14 +25,14 @@ Hälfte des verfügbaren Arbeitsspeichers des Computers ungenutzt.
|
|||
|
||||
Mit der Konfiguration \texttt{-Xmx} wird der maximal verwendbare Heap"=Speicher in der \ac{JVM} definiert.
|
||||
Dies zeigt direkt, dass es ein Problem in der Freigabe der Objekte gibt, da dass Erhöhen des verwendbaren
|
||||
Arbeitsspeicher das Problem nicht löst, sondern nur verschiebt.
|
||||
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
|
||||
ermittelt, auch hier gilt, dass weniger Aufrufe besser sind. Als letztes wird noch der verwendete Arbeitsspeicher
|
||||
vom \textit{Glassfish}"=Server vor und nach dem Aufruf ermittelt und die Differenz gebildet, hierbei sollte im besten
|
||||
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
|
||||
der \ac{JSF} ermittelt und die durchschnittlichen Zeiten mit in der Tabelle dargestellt, und auch hier ist es besser,
|
||||
wenn die Zeiten kürzer sind.
|
||||
|
@ -74,7 +74,7 @@ Da die Abfragezeiten auf der Datenbank zu gering waren, um eine Verbesserung fes
|
|||
PostgreSQL und den Payara"=Server ein Docker"=Container erzeugt und diese limitiert. Die Konfiguration ist in
|
||||
\autoref{ap:docker_config} beschrieben.
|
||||
|
||||
Mit dem neuen Aufbau ergeben sich nun eine neue Messung. Für den Speicherbedarf wird nun nicht mehr der benutzte
|
||||
Mit dem neuen Aufbau ergibt sich eine neue Messung. Für den Speicherbedarf wird nun nicht mehr der benutzte
|
||||
Speicher der Anwendung beobachtet, sondern die Speichernutzung des Docker-Containers für den Payara-Server. Auch hier
|
||||
ist es besser, wenn es keine oder nur geringe Änderungen vor und nach dem Aufruf der Webseite gibt, ein steigender Wert
|
||||
zeigt an, dass der verwendete Speicher nicht sauber freigegeben werden kann.
|
||||
|
@ -84,9 +84,9 @@ Hierzu zählt die Hauptabfrage der Dokumenten"=-Tabelle, die Ermittlung des letz
|
|||
die Ermittlung der Adressen des Autors, die Ermittlung der Koautoren, die Ermittlung der Faksimile, sowie die Ermittlung
|
||||
der Anzahl aller vorhandenen Dokumente.
|
||||
|
||||
Zusätzlich wird die Zeit des Rendern der Sicht gemessen. Hierbei wird zum einen die komplette Zeit des Renderns
|
||||
ermittelt. Innerhalb des Rendern wird dann noch die Zeit gemessen, wie lange es benötigt, die Daten aus der Datenbank
|
||||
zu laden, und in die Java"=Objekte umzuformen.
|
||||
Zusätzlich wird die Zeit des Rendern der Sicht gemessen. Die erste Messung erfasst die komplette Laufzeit die fürs Rendern
|
||||
notwendig benötigt wird. Diese Zeit wird unterteilt in die Messungen für das Laden der Daten aus der Datenbank und das Erstellen
|
||||
der Java"=Objekte inklusive dem Befüllen mit den geladenen Daten.
|
||||
|
||||
\begin{table}[h]
|
||||
\centering
|
||||
|
@ -115,7 +115,7 @@ zu laden, und in die Java"=Objekte umzuformen.
|
|||
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{CacheSize} die Anzahl der Elemente im Cache gesteuert werden. Wird diese Anzahl erreicht, dann werden zufällige
|
||||
\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.
|
||||
|
||||
|
@ -206,7 +206,7 @@ die \textit{SoftReference} nicht das Problem für den steigenden Arbeitsspeicher
|
|||
\label{tbl:measure-ojpa-active-bigger-no-softref}
|
||||
\end{table}
|
||||
|
||||
Der Vergleich zeigt, dass der Cache eine gute Optimierung bringt, aber dies nur dann gut funktioniert, wenn immer
|
||||
Der Vergleich zeigt, dass der Cache eine gute Optimierung bringt, aber dies kann nur dann gut funktionieren, wenn immer
|
||||
wieder die gleichen Objekte ermittelt werden. Sobald die Anfragen im Wechsel gerufen werden oder einfach nur die Menge
|
||||
der Objekte den Cache übersteigt, fällt die Verbesserung geringer aus.
|
||||
|
||||
|
@ -244,13 +244,14 @@ 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.
|
||||
Zum einen muss die Reference auf das \textit{ehcache} und das \textit{ehcache"=openjpa} Packet hinzugefügt werden.
|
||||
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
|
||||
an jeder Klasse die Benennung des Caches sowie die Verwendung selbst gesteuert werden. Es wird für jede Klasse ein
|
||||
eigener Cache angelegt und der Name auf den vollen Klassennamen gesetzt. Die Verwendung ist für alle Klassen
|
||||
aktiviert und müssen explizit deaktiviert werden, wenn dies nicht gewünscht ist. Als letztes muss noch der
|
||||
aktiviert und muss explizit deaktiviert werden, wenn dies nicht gewünscht ist. Als letztes muss noch der
|
||||
Cache"=Manager aktiviert werden, dieser kann entweder durch Code programmiert werden oder über eine Konfiguration
|
||||
in der \textit{ehcache.xml}.
|
||||
|
||||
|
@ -258,7 +259,7 @@ Anhand der Auswertung von \ref{tbl:measure-ehcache-active} sieht man, dass der E
|
|||
Verbesserung aufbringt. Über die Performance"=Statistik"=Webseite kann beobachtet werden, dass bei gleichen Aufrufen
|
||||
der Webseite nur die Treffer in Cache steigen, aber die Misses nicht. Ebenfalls erhöht sich die Anzahl der Objekte
|
||||
im Cache nicht. Zusätzlich steigt in diesem Fall der Speicherverbrauch nur gering bis gar nicht. Des Weiteren zeigt sich,
|
||||
dass sich die Abfragezeiten in der Datenbank nur gering verkürzt wurden, aber die Laufzeit der Webseite sich stark
|
||||
dass die Abfragezeiten in der Datenbank nur gering verkürzt wurden, aber die Laufzeit der Webseite sich stark
|
||||
verbessert hat. Dies lässt auch hier den Schluss zu, dass die Erstellung der Objekte im OpenJPA die meiste Zeit
|
||||
benötigt.
|
||||
|
||||
|
@ -289,13 +290,13 @@ 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 einem die minimalen und maximalen
|
||||
Configurations $\Rightarrow$ server"=config $\Rightarrow$ 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
|
||||
wurden. Dies ist dadurch zu erklären, dass im \ac{EJB} die Provider gelagert werden, die über Dependency Injection
|
||||
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.
|
||||
|
||||
% document, documentaddresseeperson, first/last, documentcoauthorperson, count und documentfacsimile
|
||||
|
@ -362,11 +363,11 @@ Messung aus \autoref{tbl:measure-without-cache} entspricht.
|
|||
Für die Optimierung wurden noch zusätzlich die Hints \texttt{openjpa.""hint.""OptimizeResultCount},
|
||||
\texttt{javax.""persistence.""query.""fetchSize} und \texttt{openjpa.""FetchPlan.""FetchBatchSize} gesetzt. Hierbei
|
||||
konnten je nach gesetzten Wert, keine relevanten Unterschiede festgestellt werden. Hierbei wurde der Wert auf zwei
|
||||
gesetzt, welcher viel zu gering ist. Als weiterer Test wurde der Wert auf angefragte Größte gestellt und auf den
|
||||
20"=fachen Wert der angefragten Größe.
|
||||
gesetzt, welcher viel zu gering ist. Als weiterer Test wurde der Wert auf die angefragte Größe und den
|
||||
20"=fachen Wert dieser Größe gestellt.
|
||||
|
||||
Ebenso bringt der Hint \texttt{openjpa.""FetchPlan.""ReadLockMode} auch keinen Unterschied bei der Geschwindigkeit.
|
||||
Hierbei ist erklärbar, das im Standard bei einer reinen Selektion eine Lesesperre aktiv sein muss.
|
||||
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
|
||||
zu sogenannten >>Dirty"=Reads<<, wodurch die Ausgabe verfälscht werden könnte. Daher ist diese Einstellung
|
||||
|
@ -378,10 +379,9 @@ Statement abgefragt. Mit \textit{join} wird definiert, dass abhängige Objekte d
|
|||
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
|
||||
\texthl{diese werden direkt auf die Hauptobjekte gefiltert und die Verknüpfung im} OpenJPA"=Framework durchgeführt.
|
||||
\todo{das wurde umgebaut}
|
||||
Somit muss in unserem Beispiel nicht für jedes Dokument eine einzelne Abfrage für die Koautoren durchgeführt werden,
|
||||
sondern es wird nur eine Abfrage abgesetzt für alle Dokumente die ermittelt wurden. Technisch gesehen wird die gleiche
|
||||
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
|
||||
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}.
|
||||
|
@ -428,8 +428,8 @@ if (myResultList != null && !myResultList.isEmpty()) {
|
|||
\end{lstlisting}
|
||||
|
||||
Wie in der Messung in \autoref{tbl:measure-criteria-api} zu sehen, unterscheiden sich die Abfragezeiten nur marginal
|
||||
von denen mit \ac{JPQL}. Wenn man sich den Code im Debugger betrachtet, \texthl{ist zu erkennen,} dass die zusammengesetzten
|
||||
Abfragen in den Java-Objekten fast identisch sind. Und in der Datenbank sind die Anfragen identisch zu denen über JPQL.
|
||||
von denen mit \ac{JPQL}. Wenn man sich den Code im Debugger betrachtet, lässt sich erkennen, dass die zusammengesetzten
|
||||
Abfragen in den Java-Objekten fast identisch sind. In der Datenbank sind die Anfragen identisch zu denen über JPQL.
|
||||
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
|
@ -453,10 +453,10 @@ Abfragen in den Java-Objekten fast identisch sind. Und in der Datenbank sind die
|
|||
\end{table}
|
||||
|
||||
Daher bringt die Criteria API keinen performance Vorteil gegenüber der JPQL"=Implementierung. Somit können beide
|
||||
Implementierung ohne bedenken gegeneinander ausgetauscht werden, und die verwendet werden, die für den Anwendungsfall
|
||||
Implementierungen ohne Bedenken gegeneinander ausgetauscht werden, und die verwendet werden, die für den Anwendungsfall
|
||||
einfacher umzusetzen ist.
|
||||
|
||||
Bei den Hints ist es das gleiche wie bei \ac{JPQL}. Auch hier haben die meisten Hints keinen merkbaren Einfluss. Die
|
||||
Bei den Hints ist es das Gleiche wie bei \ac{JPQL}. Auch hier haben die meisten Hints keinen merkbaren Einfluss. Die
|
||||
Einstellung \texttt{openjpa.""FetchPlan.""EagerFetchMode} liefert auch hier Optimierungen, wenn der Wert auf
|
||||
\textit{parallel} gestellt wird. Hier wird ebenfalls die Anzahl der Anfragen reduziert und damit auch die
|
||||
Geschwindigkeit optimiert.
|
||||
|
@ -612,14 +612,14 @@ vorhanden Elemente, welche die Liste der Dokumente anzeigt, kopiert und auf die
|
|||
\label{tbl:measure-materialized-view}
|
||||
\end{table}
|
||||
|
||||
Wie in \autoref{tbl:measure-materialized-view} zu sehen, bringt die Verwendung der \textit{Materialized View} eine
|
||||
Verbesserung in verschiedenen Punkten. Zum einen ist eine Verbesserung der Aufrufzeiten zu erkennen, zusätzlich fällt
|
||||
Wie in \autoref{tbl:measure-materialized-view} zu sehen ist, bringt die Verwendung der \textit{Materialized View} eine
|
||||
Verbesserung in verschiedenen Punkten. Zum einen ist eine Verbesserung der Aufrufzeiten zu erkennen, zum anderen fällt
|
||||
der Speicheranstieg weniger stark aus. Die Verbesserung der Aufrufzeiten lässt sich zusätzlich erklären, dass hier nun
|
||||
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 dem der Quellcode nochmal untersucht wurde, konnte man festellen, dass bei jeder Anfrage die gleiche Bedingung
|
||||
benötigt wurden. Da die Sicht nun explizit für dies Anfrage geschaffen wurde, wurde die Bedingungen nun direkt in die
|
||||
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
|
||||
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.
|
||||
|
||||
|
@ -654,22 +654,22 @@ 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 den erste Messung, wurde vor der Datenbankabfrage ein
|
||||
\texttt{SearchDocument} Objekt erzeugt und dieses in jedem \texttt{map}"=Aufruf zurückgegeben. Mit dieser Aufbau wurde
|
||||
\texthl{die Zeit ermittelt, um die Daten aus der Datenbank zu laden und dieses Ergebnis einmalig zu durchlaufen} ohne ein \todo{verena}
|
||||
\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
|
||||
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 schon auf 54 ms.
|
||||
erzeugt wird, ohne die Konvertierung der ermittelten Daten in das Objekt, steigt die Laufzeit bereits auf 54 ms.
|
||||
Wenn man nun noch die Konvertierung der Daten mit einbaut, erhöht sich die Laufzeit nochmals, auf nun 82 ms.
|
||||
Alleine für das Erzeugen der Objekte und der Json"=Parse Aufrufe wird die meiste Zeit aufgewendet.
|
||||
|
||||
Bei der Verwendung des Hints \texttt{openjpa.""FetchPlan.""FetchBatchSize} kann die Abfrage enorm verschlechtern. Wenn
|
||||
Bei der Verwendung des Hints \texttt{openjpa.""FetchPlan.""FetchBatchSize} kann sich die Abfrage enorm verschlechtern. Wenn
|
||||
dieser Wert zu klein oder groß definiert ist, wird die Laufzeit verschlechtert. Bei einem zu großen Wert wird die
|
||||
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} dargestellt, haben keine Auswirkung auf die Performance.
|
||||
\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
|
||||
\texttt{map}"=Funktion des eigenen Codes und daher wird der Cache nicht genutzt.
|
||||
|
||||
|
@ -697,7 +697,7 @@ die \textit{Json}"=Daten aufgerufen wird, wie beim laden der Webseite.
|
|||
\end{lstlisting}
|
||||
|
||||
Die Interpreter"=Funktion, welche in JavaScript geschrieben ist, wird benötigt um die übertragenen
|
||||
\textit{Json}"=Daten in eine darstelle Form zu bringen. Die Funktion aus dem \autoref{lst:jsf-datatable-json-convert}
|
||||
\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
|
||||
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.
|
||||
|
@ -746,7 +746,7 @@ $(document).ready(function() {
|
|||
Da nun am Client der Code ausgeführt wird, nachdem die Daten übertragen wurden, kann nicht mehr alles über das Script
|
||||
durchgeführt werden. Daher werden nun die Laufzeiten am Server und am Client zusammenaddiert. Im Schnitt benötigt der
|
||||
Aufruf auf der Serverseite nun 70 ms und am Client sind es circa 13 ms. Die summierte Laufzeit von Client und Server
|
||||
ist geringer als die reine Serverlösung und erzeugt gleichzeit weniger Last am Server. \mytodos{verena}
|
||||
ist geringer als die reine Serverlösung und erzeugt gleichzeit weniger Last am Server.
|
||||
|
||||
\section{Optimierung der Abfrage}
|
||||
\label{sec:performance-investigation-application:optimizing-query}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
Nun werden die durchgeführten Anpassungen anhand ihre Effektivität betrachtet und unter welchen äußeren Einflüssen
|
||||
diese eine Optimierung darstellen. Weiterhin werden die Nachteile der Anpassungen überprüft und und bei der Betrachtung
|
||||
der Effektivität mit beachtet. \mytodos{verena}
|
||||
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
|
||||
|
@ -25,8 +25,8 @@ wurde, ein rein technischer Ansatz.
|
|||
\section{Umgestalten der Datenbanktabellen}
|
||||
\label{sec:evaluation:new-table}
|
||||
|
||||
Hierfür wurde die aktuelle Datenstruktur untersucht um zu prüfen, ob eine Umgestaltung der Tabelle einen Verbesserung
|
||||
bringen würden. Die typische Optimierung ist die Normalisierung der Tabellenstruktur. Die Tabellenstruktur ist aktuell
|
||||
Hierfür wurde die aktuelle Datenstruktur untersucht um zu überprüfen, ob eine Umgestaltung der Tabelle einen 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.
|
||||
|
||||
Eine weitere Optimierungsstrategie besteht in der Denormalisierung, um sich die Verknüpfungen der Tabellen zu sparen.
|
||||
|
@ -75,7 +75,7 @@ Optimierungsmöglichkeiten.
|
|||
\section{Caching im OpenJPA}
|
||||
\label{sec:evaluation:caching-jpa}
|
||||
|
||||
Bei der Verwendung des OpenJPA"=Caches gibt es einige Verbesserungen in der Geschwindigkeit zu sehen. Die Höhe der
|
||||
Bei der Verwendung des OpenJPA"=Caches gibt es einige Verbesserungen bei der Geschwindigkeit zu sehen. Die Höhe der
|
||||
Optimierungen hängt stark von der gewählten Cache"=Größe und der aufgerufenen Webseiten ab. Solange die Anfragen sich
|
||||
auf die gleichen Objekte beziehen und diese alle im Cache hinterlegt werden können, fällt die Optimierung entsprechend
|
||||
hoch aus. Sobald bei den Anfragen aber häufig die zu ermittelnden Objekte sich unterscheiden und alte Objekte wieder
|
||||
|
@ -83,8 +83,8 @@ aus dem Cache entfernt werden, fällt die Performance"=Verbesserung immer gering
|
|||
|
||||
Das Entfernen der Objekte kann zwar umgangen werden, indem die häufig abgefragten Objekte gepinnt werden, was aber
|
||||
den Speicherbedarf noch weiter erhöht, da diese Objekte nicht in die Zählung der Cache"=Objekte beachtet werden.
|
||||
Was uns direkt zum größten Nachteil diese Caches kommen lässt, die notwendig Speichermenge die ständig zur Verfügung
|
||||
gestellt werden muss. Damit ist immer ein gewisser Grundbedarf notwendig, da sich der Speicher bis zum eingestellten
|
||||
Als größten Nachteil des Caches ist zu nennen, dass die notwendige Speichermenge ständig zur Verfügung gestellt
|
||||
werden muss. Damit ist immer ein gewisser Grundbedarf notwendig, da sich der Speicher bis zum eingestellten
|
||||
Grenzwert aufbaut und dann nicht mehr entleert wird. Gerade bei kleiner dimensionierten Servern stellt dies ein
|
||||
größeres Problem dar, da nun weniger Speicher für die anderen laufenden Programme, wie dem Datenbankmanagementsystem,
|
||||
zur Verfügung steht.
|
||||
|
@ -106,7 +106,7 @@ explizit im Cache aufgenommen und angepinnt werden.
|
|||
Die Optimierung über die gespeicherten Anfragen brachte keine Verbesserung hervor. Dies ist dadurch erklärbar, dass
|
||||
für die diese Art nur Anfragen verwendet werden, die keinerlei Bedingungen besitzen. In diesem Fall sind in der Tabelle
|
||||
noch nicht freigegebene und ungültige Datensätze gespeichert, daher müssen diese vor dem Übertragen herausgefiltert
|
||||
werden. Aus diesem Grund werden die Anfragen in diesem Cache nicht gespeichert werden.
|
||||
werden. Aus diesem Grund werden die Anfragen in diesem Cache nicht gespeichert.
|
||||
|
||||
Dadurch ist dieser Cache für eine Performance"=Verbesserung in dem Fall der Dokumentenliste nicht anwendbar.
|
||||
|
||||
|
@ -153,14 +153,14 @@ keine nennenswerten Einfluss auf die Laufzeit der Abfragen und Übertragung in d
|
|||
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.
|
||||
|
||||
Anders verhält sich dies mit den Einstellungen für EagerFetchMode, welche definiert wie die Daten für abhängige Klasse
|
||||
Anders verhält sich dies mit der Einstellung für \texttt{EagerFetchMode}, welche definiert, wie die Daten für abhängige Klassen
|
||||
ermittelt werden. Bei der Umstellung auf \textit{parallel} konnte für die Ermittlung der Dokumente einiges an Performance gewonnen
|
||||
werden. Das liegt daran, dass nun für die abhängigen Objekte, wie den Koautoren, nicht pro Dokument eine Anfrage an die
|
||||
Datenbank gestellt wird, sondern es werden alle Koautoren für die ermittelten Dokumente auf einmal ermittelt. Die
|
||||
Zuordnung der Koautoren zu dem Dokument wird dann nun im Framework und nicht mehr durch die Datenbank durchgeführt.
|
||||
Diese Abarbeitung reduziert viele einzelne Abfragen und somit auch den entsprechend Overhead im Framework.
|
||||
|
||||
Auf Grund dessen ist die Entscheidung der Technik für die Performance irrelevant und es kann das genutzt werden, was für
|
||||
Folglich ist die Entscheidung der Technik für die Performance irrelevant und es kann das genutzt werden, was für
|
||||
jeweiligen Einsatzzweck besser beziehungsweise einfacher zu programmieren ist. Das Setzen der richtigen Hints wiederrum
|
||||
ist in beiden Fällen äußerst wichtig. Explizit bei der EagerFetchMode muss vorher darüber nachgedacht werden, wie viele
|
||||
abhängige Objekttypen es zu dieser Klasse gibt, welche dazu geladen werden sollen und von welcher Anzahl an Objekte
|
||||
|
@ -172,11 +172,11 @@ Gleiches gilt dem Hint SubclassFetchMode, dieser steuert dimensionierte Abfragen
|
|||
|
||||
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 der 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 über den Datenbestand die größte Zeit
|
||||
gewidmet wird.
|
||||
Briefe einmalig eingepflegt wurden, nur noch selten Änderungen erfahren. Die 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
|
||||
wie bei einer Tabelle auf der Festplatte gespeichert sind. Dieser Nachteil ist in der Dokumentliste vernachlässigbar,
|
||||
|
@ -191,14 +191,14 @@ konnten schon viele zusätzliche Abfragen eingespart werden, da diese nicht mehr
|
|||
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 zum einen Last vom Server genommen werden und die gesamte Ausführungszeit nochmals
|
||||
optimieren. Die Wandlung der Daten in \textit{HTML}"=Objekte ist eine Kernkompetenz von JavaScript und damit auch bei
|
||||
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
|
||||
schwächeren Clients in kurzer Zeit durchführbar.
|
||||
|
||||
Als weiteren Punkt ist anzumerken, das der Speicherbedarf des Webserver relativ konstant bleibt ohne das ein Cache
|
||||
verwendet wird. Der größte Unterschied zur Standardimplementierung ist die Verwendung von eigenen Code um die Objekte
|
||||
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
|
||||
zu erstellen und zu befüllen und es nicht durch das OpenJPA"=Framework durchführen zu lassen.
|
||||
Dies legt den Schluss nahe, dass es Probleme in der Speicherverwaltung der Objekte im OpenJPA"=Framework existieren.
|
||||
Dies legt den Schluss nahe, dass Probleme in der Speicherverwaltung der Objekte im OpenJPA"=Framework existieren.
|
||||
|
||||
Zusammenfassend ist zu sagen, dass die \textit{Materialized View} eine gute Wahl ist, um die Listendarstellungen
|
||||
zu optimieren. Mit dieser Technik können zum einen die Abfragezeiten optimiert werden, wodurch gleichzeit die
|
||||
|
@ -209,7 +209,7 @@ ist oder direkt auf denormalisierte Daten umgestellt werden sollte, weil der zus
|
|||
die Quelle ist.
|
||||
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 aus dem Cache. Wenn dieser voll ist und wird ein Zugriff auf diese entfernten Objekte
|
||||
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
|
||||
stabiler.
|
||||
|
||||
|
@ -217,20 +217,21 @@ stabiler.
|
|||
\label{sec:evaluation:optimize-query}
|
||||
|
||||
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 langsam werden. Diese können durch entsprechende Indexe
|
||||
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.
|
||||
|
||||
Der Abfrageplan der Hauptabfrage wurde visuell untersucht und zeigt, dass das Hauptproblem die nicht eingeschränkte
|
||||
Datenmenge der Haupttabelle \textit{document} ist. Dadurch werden zum einen die anderen Tabellen komplett dazu geladen
|
||||
und es werden trotz direkter Primary Key Bedingungen keine Zugriffe über die Index durchgeführt. Für den PostgreSQL
|
||||
Datenmenge der Haupttabelle \textit{document} ist. Dadurch werden die anderen Tabellen komplett geladen
|
||||
anstatt die Zugriffe über die vorhandenen Indexe durchzuführen, obwohl die Bedingungen über die Primary Key definiert
|
||||
sind. Für den PostgreSQL
|
||||
ist es laut Berechnung kostengünstiger mit einem \textit{Seq Scan}, was einem kompletten Durchlaufen der Tabelle
|
||||
entspricht, zu arbeiten.
|
||||
|
||||
Um dies zu optimieren, wurde über eine \textit{Common Table Expression} zuerst die eingeschränkten Datenzeilen
|
||||
ermittelt, dieser mit der Haupttabelle verknüpft und nun die anderen Tabellen dazugenommen. Hierdurch konnten die
|
||||
ermittelt, dieser mit der Haupttabelle verknüpft und nun die anderen Tabellen dazugenommen. Hierdurch konnte die
|
||||
Zeilenanzahl während der Verarbeitung enorm verringert werden, wodurch einige der Verknüpfungen auf Indexzugriffe
|
||||
umgestellt wurden. Durch die Umstellung konnte die Abfragezeit um mehr als das dreifache reduziert wurde.
|
||||
umgestellt wurden. Durch die Umstellung konnte die Abfragezeit um mehr als das dreifache reduziert werden.
|
||||
|
||||
Mit dieser Art der Umstellung können Abfragen optimiert werden, die fürs Paging verwendet werden und die Abfrage aus
|
||||
mehrere Tabellen besteht. Das Wichtigste hierbei ist, dass die Bedingungen und die Sortierkriterien auf der
|
||||
|
|
|
@ -12,19 +12,17 @@
|
|||
Die Untersuchungen am Beispiel des Wedekind"=Projektes zeigen, dass mehrere Optimierungsmöglichkeiten in den
|
||||
Briefeditionen existieren. Für die Untersuchung wurde sich auf die Dokumentenliste beschränkt und anhand dieser
|
||||
die Optimierung implementiert, untersucht und jeweils mit der Ausgangsmessung vergleichen. Für die Messung wurden
|
||||
Skripte erstellt, die auf dem gleichen Computer wie der Webserver und der Datenbankserver laufen, damit diese auch
|
||||
Skripte erstellt, welche auf dem gleichen Computer wie der Webserver und der Datenbankserver laufen, damit diese auch
|
||||
vergleichbar bleiben und externe Einflussfaktoren minimiert werden.
|
||||
|
||||
\mytodos{den Absatz hier drin lassen oder raus?}
|
||||
%Messung zeigt wo die Probleme liegen! hier noch ausformulieren
|
||||
Durch die Ausgangsmessungen war erkennbar, dass der größte Teil der Verarbeitungszeit im Bereitstellen der Entitäten
|
||||
benötigt wird. Die Messung der Abfragen auf der Datenbank wiederum konnte die hohe Verarbeitungszeit nicht bestätigen,
|
||||
daher lag hier schon die Vermutung nahe, dass der Großteil der Zeit im ORM"=Mapper verloren geht.
|
||||
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.
|
||||
|
||||
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
|
||||
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 wurde auf Grund von technischen Einschränkungen nicht weiterverfolgt.
|
||||
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
|
||||
|
@ -34,7 +32,7 @@ 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
|
||||
speichern, sind die Verbesserung gut sichtbar. Ab dem Zeitpunkt ab dem Objekte aus dem Cache entfernt werden müssen,
|
||||
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
|
||||
|
@ -44,41 +42,41 @@ In beiden Fällen der Optimierung über die Nutzung eines Caches, konnte durch d
|
|||
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.
|
||||
|
||||
Bei dem Vergleich der unterschiedlichen Abfragemethoden Criteria API und JPQL konnte keine Unterschied in der
|
||||
Bei dem Vergleich der unterschiedlichen Abfragemethoden Criteria API und JPQL konnte kein Unterschied in der
|
||||
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 wurde, sondern alle Daten auf einmal
|
||||
bezweckt das die unterlagerten Daten nicht einzeln für jede Zeile ermittelt wurden, 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 in eigenen Code erstellt werden und nicht durch das OpenJPA"=Framework. Hierbei konnte noch nachgewiesen
|
||||
die Objekte im eigenen Code erstellt werden und nicht durch 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 Datensatze direkt am Anfang auf die angefragte Menge reduziert, wodurch die Anzahl der zu betrachteten Datensätze
|
||||
für die weiteren Verlinkungen enorm reduziert wurden. Somit konnte der Datenbankserver bei diesen Verlinkung auf Indexe
|
||||
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
|
||||
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 den ORM"=Mapper vorhanden ist. Welche der
|
||||
Optimierungen verwendet werden, liegt zum einen an der Komplexität der Abfrage und der bereitgestellten Ressourcen
|
||||
Briefeditionen zu beschleunigen und das das größte Optimierungspotential in dem ORM"=Mapper liegt. Welche der
|
||||
Optimierungen verwendet werden, liegt an der Komplexität der Abfrage und der bereitgestellten Ressourcen
|
||||
des Servers.
|
||||
|
||||
\section{Ausblick}
|
||||
\label{sec:summary_and_outlook:outlook}
|
||||
|
||||
Die Untersuchungen zeigen, dass die Schichten über OpenJPA weitestgehend optimal umgesetzt sind, beziehungsweise wenig
|
||||
Möglichkeiten für eine Optimierungen zu lassen. Einzig das Parsen von Json ist in einem Webbrowser schneller als im
|
||||
Möglichkeiten für eine Optimierungen zulassen. Einzig das Parsen von Json ist in einem Webbrowser schneller als im
|
||||
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
|
||||
können.
|
||||
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,
|
||||
|
|
|
@ -5,17 +5,17 @@
|
|||
\pdfbookmark[0]{Zusammenfassung}{Zusammenfassung}
|
||||
\chapter*{Zusammenfassung}
|
||||
Die Briefedition des Wedekind"=Projektes stellt die Korrespondenz von Frank Wedekind als Online"=Volltextdatenbank
|
||||
zur Verfügung um die Forschung an Frank Wedekind zu fokussieren. Um die Akzeptanz der Webseite zu erhöhen, damit
|
||||
weitere Forscher sich mit dem Thema beschäftigen, soll die Reaktionszeit für die Anfragen reduziert werden.
|
||||
zur Verfügung, um die Forschung an Frank Wedekind zu fokussieren. Um die Akzeptanz der Webseite zu erhöhen, damit
|
||||
sich weitere Forscher mit dem Thema beschäftigen, soll die Reaktionszeit für die Anfragen reduziert werden.
|
||||
|
||||
Diese Arbeit betrachtet die verschiedenen Layer der Anwendung und die jeweiligen Optimierungsmöglichkeiten. Hierbei
|
||||
wird ein rein technischer Ansatz gewählt, der durch Skript basierte Messungen überprüft und ausgewertet wird.
|
||||
wird ein rein technischer Ansatz gewählt, der durch skriptbasierte Messungen überprüft und ausgewertet wird.
|
||||
Betrachtet werden hierbei die Auswirkungen der verschiedenen Caches, die Abfragesprachen, eine Umstellung der
|
||||
Abfragen auf \textit{Materialized Views} und die Optimierungsmöglichkeiten der Abfragen.
|
||||
|
||||
Es zeigt sich, dass die Ebenen unterschiedlich gute Optimierungsmöglichkeiten besitzen und die Caches die einfachste
|
||||
Art der Optimierung sind, stattdessen benötigen diese zusätzliche Ressourcen im Sinne des Arbeitsspeichers.
|
||||
Art der Optimierung ist, stattdessen benötigen diese zusätzliche Ressourcen im Sinne des Arbeitsspeichers.
|
||||
Die Umstellung der \textit{Materialized View} inklusive der Zusammenfassung der unterlagerten Daten in eine Zeile
|
||||
zeigt das größte Optimierungspotential. Durch die Umstellung der Abfragen kann ebenfalls die Verarbeitungszeit
|
||||
reduziert werden, ist durch den größeren Anteil des ORM"=Mapper aber nicht stark ausschlaggebend.
|
||||
reduziert werden, dies ist durch den größeren Anteil des ORM"=Mapper nicht stark ausschlaggebend.
|
||||
\end{otherlanguage}
|
||||
|
|
|
@ -4,19 +4,18 @@
|
|||
\begin{otherlanguage}{american}
|
||||
\pdfbookmark[0]{Abstract}{Abstract}
|
||||
\chapter*{Abstract}
|
||||
\mytodos{Dies am Ende noch Ausfüllen!!!}
|
||||
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
|
||||
website so that more researchers can deal with the subject, the response time for inquiries is to be reduced.
|
||||
|
||||
A short summary of the contents in English of about one page. The following points should be addressed in particular:
|
||||
\begin{itemize}
|
||||
\item Motivation: Why did this work come about? Why is the topic of the work interesting (for the general public)? The motivation should be abstracted as far as possible from the specific tasks that may be given by a company.
|
||||
\item Content: What is the content of this thesis? What exactly is covered in the thesis? The methodology and working method should be briefly discussed here.
|
||||
\item Results: What are the results of this work? A brief overview of the most important results as a teaser to read the complete thesis.
|
||||
\end{itemize}
|
||||
\medskip
|
||||
This paper looks at the different layers of the application and the respective optimization options. A purely
|
||||
technical approach is chosen here, which is checked and evaluated using script-based measurements. The effects
|
||||
of the different caches, the query languages, a conversion of the queries to materialized views and the
|
||||
optimization possibilities of the queries are considered. views and the optimization possibilities of the queries.
|
||||
|
||||
\noindent
|
||||
BTW: A great guide by Kent Beck how to write good abstracts can be found here:
|
||||
\begin{center}
|
||||
\url{https://plg.uwaterloo.ca/~migod/research/beckOOPSLA.html}
|
||||
\end{center}
|
||||
It can be seen that the levels have different optimization options and that the caches are the simplest type of
|
||||
optimization, but instead require additional resources in terms of working memory. Converting the materialized
|
||||
view, including combining the underlying data into one line, shows the greatest potential for optimization. The
|
||||
processing time can also be reduced by converting the queries, but this is not very decisive due to the larger
|
||||
proportion of the ORM mapper.
|
||||
\end{otherlanguage}
|
||||
|
|
BIN
thesis.pdf
BIN
thesis.pdf
Binary file not shown.
Loading…
Reference in a new issue