Daily CheckIn
This commit is contained in:
parent
f2f1122846
commit
ebec44cdee
15 changed files with 276 additions and 260 deletions
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
|
@ -4,6 +4,7 @@
|
|||
"autovacuum",
|
||||
"denormalisierte",
|
||||
"Denormalisierung",
|
||||
"deserialisiert",
|
||||
"editionswissenschaftlich",
|
||||
"EFFW",
|
||||
"Ehcache",
|
||||
|
@ -57,6 +58,8 @@
|
|||
"adressee",
|
||||
"ajax",
|
||||
"american",
|
||||
"appuser",
|
||||
"appuserrole",
|
||||
"asadmin",
|
||||
"authorperson",
|
||||
"birthstartday",
|
||||
|
@ -80,6 +83,7 @@
|
|||
"endday",
|
||||
"endmonth",
|
||||
"endyear",
|
||||
"extendedbiography",
|
||||
"ferniunithesis",
|
||||
"firstname",
|
||||
"fmtutil",
|
||||
|
@ -105,6 +109,7 @@
|
|||
"searchdocument",
|
||||
"searchfulltext",
|
||||
"searchreference",
|
||||
"seqscan",
|
||||
"servlet",
|
||||
"servlets",
|
||||
"sitecity",
|
||||
|
|
|
@ -73,7 +73,7 @@ zu verringern. Um Anfragen die den Zugriff auf die Festplatte benötigen effizie
|
|||
every fit/.style={inner sep=1em,draw}
|
||||
]
|
||||
%https://docs.oracle.com/javaee/6/tutorial/doc/bnacj.html
|
||||
\node (browser) [block] {WebBrowser};
|
||||
\node (browser) [block] {Webbrowser};
|
||||
\node (fitClient) [fit=(browser)] {};
|
||||
\node [left] at (fitClient.west) {Client};
|
||||
|
||||
|
@ -113,13 +113,13 @@ von Datenbankverbindungen zu definieren \citep[68]{MüllerWehr2012}. Dadurch kan
|
|||
gehalten werden als die Anzahl der Benutzer die an der Anwendung arbeiten. Zusätzlich werden die Transaktionen über
|
||||
\textit{Stateful Session-Bean (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 Performanz-Problemen
|
||||
Entities in den \textit{Persistenzkontext} geladen werden. Da dies häufig zu Speicher"= und damit Performance"=Problemen
|
||||
\citep[79]{MüllerWehr2012} führen kann, muss hier darauf geachtet werden, nicht mehr benötigte Entities aus dem
|
||||
\textit{Persistenzkontext} zu lösen.
|
||||
|
||||
\subsection{Glassfish - Java Persinstance API}
|
||||
|
||||
Die \textit{Java Persistence API (JPA)} wird als First-Level-Cache in Java-EE-An\-wen\-dung verwendet, hier nehmen die
|
||||
Die \textit{\ac{JPA}Java Persistence API (JPA)} wird als First-Level-Cache in Java-EE-An\-wen\-dung verwendet, hier nehmen die
|
||||
Objekte einen von vier Zuständen ein \citep[57]{MüllerWehr2012}. Im Zustand \textit{Transient} sind die Objekt erzeugt,
|
||||
aber noch nicht in den Cache überführt worden. Wenn diese in den Cache überführt worden sind, nehmen sie den Zustand
|
||||
\textit{Verwaltet} ein. Ist das Objekt aus dem Cache und der Datenbank entfernt worden, nimmt es den Zustand
|
||||
|
|
|
@ -12,7 +12,7 @@ Um die Messungen etwas zu vereinfachen wurde ein Skript erstellt um die Aufrufe
|
|||
Messungen durchzuführen werden die Befehl, 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,
|
||||
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.
|
||||
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
\chapter{JSF Performance Measure}
|
||||
\label{ap:jsf_performance_measure}
|
||||
|
||||
Für die Protokollierung der Abläufe im \ac{JSF} werden zwei Klassen benötigt. Die Factory \ref{lst:logger_factory},
|
||||
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.
|
||||
Zusätzlich muss in der Konfiguration \textbf{faces-config.xml} noch angepasst werden, wie in
|
||||
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.
|
||||
|
||||
\includecode[java]{chapters/thesis/appendix06_Logger.java}{lst:logger}{Vdi Logger}
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
\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 wird
|
||||
werden, dass die Anwendung immer in kurzer Zeit reagiert oder entsprechende Anzeigen dargestellt werden
|
||||
um eine längere Bearbeitung anzuzeigen.
|
||||
|
||||
%\section{Motivation}
|
||||
|
@ -48,7 +50,7 @@ der Hochschule Darmstadt und der Fernuni Hagen umgesetzt und durch die Deutsche
|
|||
|
||||
Das entstandene Pilotprojekt ist eine webbasiert Anwendung, die aktuell unter \url{http://briefedition.wedekind.h-da.de}
|
||||
eingesehen werden kann. Hierbei wurden sämtliche bislang bekannte Korrespondenzen in dem System digitalisiert. Die
|
||||
Briefe selbst werden im etablierten TEI-Format gespeichert und über einen WYSIWYG-Editor von den Editoren und
|
||||
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
|
||||
|
@ -61,10 +63,8 @@ Die aktuelle Umsetzung beinhaltet die bisher definierten Anforderungen vollstän
|
|||
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 der Arbeit ist es, die Abfragedauer zu verringern, wodurch die Performance der Oberfläche signifikant
|
||||
verbessert wird.
|
||||
|
||||
Hierbei ist auch ein Vergleich mit anderen Techniken angedacht.
|
||||
Das Ziel dieser Arbeit ist es, die Abfragedauer zu verringern, wodurch die Performance der Oberfläche signifikant
|
||||
verbessert wird. \mytodos{verena}
|
||||
|
||||
\section{Gliederung}
|
||||
\label{sec:intro:structure}
|
||||
|
@ -79,21 +79,22 @@ Hierzu gehören zum einen die Einstellungen der verwendeten Software, und zum an
|
|||
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"=Untersuchung in \autoref{ch:performance-checking} werden nun die Konzepte angewandt, um
|
||||
Bei den Performance"=Untersuchungen im \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.
|
||||
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"=Untersuchung der Anwendung aufzeigt.
|
||||
Performance"=Untersuchungen der Anwendung aufzeigt.
|
||||
|
||||
Zuerst wird im \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 dann in Abhängigkeit zur Ausgangsmessung die Optimierung bewertet.
|
||||
wird mit der Ausgangsmessung verglichen und bewertet.
|
||||
|
||||
Nach der Optimierung kommt nun die Evaluierung im \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.
|
||||
|
||||
Zum Abschluss im Kapitel \ref{ch:summary_and_outlook} wird explizit die Anpassungen dargestellt, die zu einer
|
||||
merklichen Verbesserung geführt haben und wie diese entsprechend umgesetzt werden müssen. Zusätzliche wird
|
||||
\todo{verena}
|
||||
Zum Abschluss im \autoref{ch:summary_and_outlook} \texthl{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.
|
||||
|
|
|
@ -6,16 +6,17 @@
|
|||
Da die Anwendung als Webseite umgesetzt ist, ist der zugehörige Client für den Benutzer ein Webbrowser. Dies bedeutet,
|
||||
dass jeder Wechsel einer Seite oder eine Suchanfrage als Web"=Request an den Server geschickt wird. Solch ein Web"=Request
|
||||
geht durch mehrere Schichten des Server"=System bis die Antwort an den Client zurückgesendet wird, wie in
|
||||
\ref{fig:webrequest} dargestellt.
|
||||
\autoref{fig:webrequest} dargestellt.
|
||||
|
||||
Es wird ab hier immer von einem \textit{Glassfish}"=Server geredet. In der Praxis wird ein \textit{Payara}"=Server
|
||||
\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
|
||||
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 diese mit regelmäßigen Aktualisierungen versorgt wird. In dem weiteren Text
|
||||
wird weiterhin der Begriff \textit{Glassfish} verwendet.
|
||||
und ist für Produktivumgebungen gedacht, da dieser mit regelmäßigen Aktualisierungen versorgt wird. In dem weiteren 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
|
||||
empfangen wird. In diesem wird anhand des definierten Routing entschieden, an welchen \textit{Controller} im \ac{JSF}
|
||||
empfangen wird. In diesem wird anhand des definierten Routing entschieden, an welchen \textit{Controller} im \textit{\ac{JSF}}
|
||||
die Anfrage weitergeleitet und verarbeitet wird. In diesem wird die Darstellung der Webseite geladen und die Anfragen
|
||||
für den darzustellenden Datenbestand abgeschickt.
|
||||
|
||||
|
@ -25,7 +26,7 @@ an das unterlagerte Datenbankmanagementsystem \textit{PostgreSQL} weitergeleitet
|
|||
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
|
||||
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
|
||||
\textit{Services} die Datenstrukturen auf.
|
||||
|
||||
|
@ -36,7 +37,7 @@ zu verringern. Um Anfragen die den Zugriff auf die Festplatte benötigen effizie
|
|||
every fit/.style={inner sep=1em,draw}
|
||||
]
|
||||
%https://docs.oracle.com/javaee/6/tutorial/doc/bnacj.html
|
||||
\node (browser) [block] {WebBrowser};
|
||||
\node (browser) [block] {Webbrowser};
|
||||
\node (fitClient) [fit=(browser)] {};
|
||||
\node [left] at (fitClient.west) {Client};
|
||||
|
||||
|
@ -73,11 +74,11 @@ 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 Verbindung geringer
|
||||
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
|
||||
\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 Performanz"=Problemen
|
||||
Entities in den \textit{Persistenzkontext} geladen werden. Da dies häufig zu Speicher"~ und damit Performance"=Problemen
|
||||
\citep[79]{MüllerWehr2012} führen kann, muss hier darauf geachtet werden, nicht mehr benötigte Entities aus dem
|
||||
\textit{Persistenzkontext} zu lösen.
|
||||
|
||||
|
@ -85,40 +86,41 @@ Entities in den \textit{Persistenzkontext} geladen werden. Da dies häufig zu Sp
|
|||
\label{sec:basics:jpa}
|
||||
|
||||
Die \textit{\ac{JPA}} wird als First"=Level"=Cache in Java"=EE"=Anwendung verwendet, hier nehmen die
|
||||
Objekte einen von vier Zuständen ein \citep[57]{MüllerWehr2012}. Im Zustand \textit{Transient} sind die Objekt erzeugt,
|
||||
Objekte einen von vier Zuständen ein \citep[57]{MüllerWehr2012}. Im Zustand \texttt{Transient} sind die Objekte erzeugt,
|
||||
aber noch nicht in den Cache überführt worden. Wenn diese in den Cache überführt worden sind, nehmen sie den Zustand
|
||||
\textit{Verwaltet} ein. Ist das Objekt aus dem Cache und der Datenbank entfernt worden, nimmt es den Zustand
|
||||
\textit{Gelöscht} an. \textit{Losgelöst} ist der letzte Zustand, bei dem das Objekt aus dem Cache entfernt worden ist,
|
||||
\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.
|
||||
|
||||
Eine Menge von Objekten wird als \textit{Persistenzkontext} bezeichnet. Solange die Objekte dem
|
||||
\textit{Persistenzkontext} zugeordnet sind, also den Zustand \textit{Verwaltet} besitzen, werden diese auf Änderungen
|
||||
überwacht, um sie am Abschluss mit der Datenbank zu synchronisieren. In der Literatur wird hierzu der Begriff
|
||||
\textit{Persistenzkontext} zugeordnet sind, also den Zustand \texttt{Verwaltet} besitzen, werden diese auf Änderungen
|
||||
überwacht, um diese am Abschluss mit der Datenbank zu synchronisieren. In der Literatur wird hierzu der Begriff
|
||||
\textit{Automatic Dirty Checking} verwendet \citep[61]{MüllerWehr2012}.
|
||||
|
||||
\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}.
|
||||
Gegen die Verwendung spricht, dass die Daten im \textit{Second Level Cache} explizit über Änderungen informiert werden
|
||||
müssen, welche sonst beim nächsten Aufruf veraltete Werte liefern. Ebenfalls benötigt so ein Cache einen höheren Bedarf
|
||||
\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
|
||||
an Arbeitsspeicher, in dem die Daten parallel zur Datenbank bereitgestellt werden, daher ist die Benutzung nur
|
||||
problemlos bei Entities möglich, auf die meist lesend zugegriffen wird.
|
||||
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}
|
||||
bezeichnet) und Query-Cache unterschieden. Über die Funktionen \texttt{find()} und \texttt{refresh()} oder einer Query
|
||||
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
|
||||
zurückliefern, aber nicht das Entity selbst. Hierbei kann genau gesteuert werden, welche Entity in den Cache abgelegt
|
||||
wird und welche nicht. Ebenfalls kann auf Klassenbasis der zugehörige Cache definiert werden, um eine bessere
|
||||
werden und welche nicht. Ebenfalls kann auf Klassenbasis der zugehörige Cache definiert werden, um eine bessere
|
||||
Last-Verteilung beim Zugriff zu ermöglichen \citep[314]{MüllerWehr2012}.
|
||||
|
||||
Im \textit{Query-Cache} werden die Abfragen beziehungsweise die Eigenschaften einer Abfrage und die zurückgelieferten Ids der
|
||||
Entities gespeichert. Bei einen erneuten Aufruf dieser Abfrage werden die referenzierten Objekte aus dem
|
||||
\textit{Objekt-Cache} zurückgegeben. Bei veränderten referenzierten Entities wird der \textit{Query-Cache} nicht
|
||||
genutzt und die betroffenen Abfragen werden unverzüglich aus dem \textit{Query-Cache} entfernt
|
||||
Im \textit{Query"=Cache} werden die Abfragen beziehungsweise die Eigenschaften einer Abfrage und die zurückgelieferten Ids der
|
||||
Entities gespeichert. Bei einem erneuten Aufruf dieser Abfrage werden die referenzierten Objekte aus dem
|
||||
\textit{Objekt"=Cache} zurückgegeben. Bei veränderten referenzierten Entities wird der \textit{Query"=Cache} nicht
|
||||
genutzt und die betroffenen Abfragen werden unverzüglich aus dem \textit{Query"=Cache} entfernt
|
||||
\citep[316]{MüllerWehr2012}.
|
||||
|
||||
Um zu prüfen, ob die Einstellungen sinnvoll gesetzt sind, kann in OpenJPA eine Cache"=Statistik abgefragt werden. Mit
|
||||
|
@ -129,20 +131,20 @@ 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 \textit{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 \textit{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.
|
||||
|
||||
Der \textit{work\_mem} definiert die Obergrenze des zur Verfügung gestellt Hauptspeichers pro Datenbankoperation wie
|
||||
effizientes Sortieren, Verknüpfen oder Filtern. Ebenso wird im Falle eines zu klein gewählten Speichers auf temporäre
|
||||
Dateien auf der Festplatte ausgewichen, was signifikanten Leistungseinbrüchen zur Folge haben kann.
|
||||
Der \texttt{work\_mem} definiert die Obergrenze des zur Verfügung gestellt Hauptspeichers pro Datenbankoperation wie
|
||||
effizientes sortieren, verknüpfen oder filtern. Ebenso wird im Falle eines zu klein gewählten Speichers auf temporäre
|
||||
Dateien auf der Festplatte ausgewichen, was signifikante Leistungseinbrüche zur Folge haben kann.
|
||||
|
||||
Die \textit{maintenance\_work\_mem} wird bei Verwaltungsoperationen wie Änderungen und Erzeugungen von Datenbankobjekten
|
||||
Die \texttt{maintenance\_work\_mem} wird bei Verwaltungsoperationen wie Änderungen und Erzeugungen von Datenbankobjekten
|
||||
als Obergrenze definiert. Die Wartungsaufgabe \texttt{VACUUM}, welche die fragmentierten Tabellen aufräumt und
|
||||
somit die Performance hebt, beachtet die Obergrenze ebenfalls.
|
||||
|
||||
|
@ -153,7 +155,7 @@ Die Wartung des Datenbanksystems ist eine der wichtigsten Aufgaben und sollte re
|
|||
durchgeführt werden, damit die Performance des Systems durch die Änderungen des Datenbestands nicht einbricht
|
||||
\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 \textit{autovacuum\_work\_mem} gesondert definiert werden \citep{PostgresPro:Chap20.4:2023}.
|
||||
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}
|
||||
\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.
|
||||
|
@ -169,11 +171,11 @@ 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 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 der wichtigsten Kennzeichen hierbei ist, ob die Zeilenschätzung akkurat war.
|
||||
Größere Abweichungen weißen 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
|
||||
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,
|
||||
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.
|
||||
|
|
|
@ -11,34 +11,34 @@ auf mögliche Optimierungen untersucht und bewertet.
|
|||
\section{Allgemeine Betrachtung des Systems}
|
||||
\label{sec:concept:viewsystem}
|
||||
|
||||
Für die Untersuchung des Systems wird der direkte Zugang zum Server benötigt. Hierbei werden zuerst die im Kapitel
|
||||
\ref{sec:basics:services} beschriebenen Einstellungen überprüft.
|
||||
Für die Untersuchung des Systems wird der direkte Zugang zum Server benötigt. Hierbei werden zuerst die im
|
||||
\autoref{sec:basics:services} beschriebenen Einstellungen überprüft.
|
||||
|
||||
Zuerst wird am PostgreSQL"=Server die Konfiguration der Speicher mit der Vorgabe für Produktivsysteme abgeglichen.
|
||||
Hierunter fallen die Einstellungen für die \textit{shared\_buffers}, der bei einem Arbeitsspeicher von mehr als 1 GB
|
||||
Hierunter fallen die Einstellungen für die \texttt{shared\_buffers}, der bei einem Arbeitsspeicher von mehr als 1 GB
|
||||
circa 25\% des Arbeitsspeicher besitzen sollte \cite{PostgresC20.4:2024}.
|
||||
|
||||
Bei der Einstellung \textit{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. Und nur bei
|
||||
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.
|
||||
|
||||
Der Speicher, der für eine Abfrage verwendet werden darf, wird über die Konfiguration \textit{work\_mem} gesteuert.
|
||||
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 \textit{shared\_buffers} dividiert durch \textit{max\_connections} \citep{ConfigTo12:online}.
|
||||
Sollte der 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 \textit{log\_temp\_files} auf 0
|
||||
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
|
||||
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
|
||||
\textit{maintenance\_work\_mem} gesetzt. Dieser Wert sollte 5\% des verfügbaren Arbeitsspeicher entsprechen und größer
|
||||
als \textit{work\_mem} sein.
|
||||
Für die Wartungsaufgaben wie VACUUM oder dem Erstellen von Indexen wird die Begrenzung über die Einstellung
|
||||
\texttt{maintenance\_work\_mem} gesetzt. Dieser Wert sollte 5\% des verfügbaren Arbeitsspeicher entsprechen und größer
|
||||
als \texttt{work\_mem} sein.
|
||||
|
||||
Dann wird mit dem Systemtools, wie den Konsolenanwendungen \textit{htop} und \textit{free}, die Auslastung des Servers
|
||||
Nachfolgend wird mit dem Systemtools, wie den Konsolenanwendungen \textit{htop} und \textit{free}, die Auslastung des Servers
|
||||
ü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 nicht die 70\% überschreiten, für kurze Spitzen wäre dies zulässig. Da sonst der
|
||||
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.
|
||||
|
||||
|
@ -48,14 +48,14 @@ wodurch der aktuell nicht verwendete in die Page"=Datei ausgelagert wird. Hierdu
|
|||
diese Elemente drastisch.
|
||||
|
||||
Die Zugriffsgeschwindigkeit, die Zugriffszeit sowie die Warteschlange an der Festplatte zeigt deren Belastungsgrenze auf.
|
||||
Hierbei kann es mehrere Faktoren geben. Zum einem führt das Paging des Arbeitsspeicher zu erhöhten Zugriffen. Ein zu
|
||||
klein gewählter Cache oder gar zu wenig Arbeitsspeicher erhöhen die Zugriffe auf die Festplatte, da weniger
|
||||
In diesem Fall kann es mehrere Faktoren geben. Zum einem führt das Paging des Arbeitsspeicher zu erhöhten Zugriffen.
|
||||
Ein zu klein gewählter Cache oder gar zu wenig Arbeitsspeicher erhöhen die Zugriffe auf die Festplatte, da weniger
|
||||
zwischengespeichert werden kann und daher diese Daten immer wieder direkt von der Festplatte geladen werden müssen.
|
||||
|
||||
\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.
|
||||
|
||||
|
@ -71,8 +71,8 @@ abgelaufen ist. Ebenso wird nach Standorten sortiert, um zu ermitteln welchen Pe
|
|||
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 \ref{lst:documentlist} gezeigt. Zusätzlich wird für jedes
|
||||
dargestellte Dokument eine zusätzliche Abfrage durchgeführt, die in \ref{lst:documentlist_sub} zeigt, dass auch hier
|
||||
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
|
||||
weitere Relationen notwendig sind.
|
||||
|
||||
\includecode[SQL]{chapters/thesis/chapter03_documentlist.sql}{lst:documentlist}{Generische Abfrage der Dokumentenliste}
|
||||
|
@ -82,7 +82,7 @@ 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 Kapitel \ref{ch:basics} dargestellt, besteht die eigentliche Anwendung aus mehreren Schichten. Die
|
||||
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.
|
||||
|
||||
|
@ -92,7 +92,7 @@ bereitgestellt, um die Daten Live vom Server verfolgen zu können. Zusätzlich w
|
|||
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
|
||||
Klassen soll ermittelt und die Statistik"=Webseite um diese Daten erweitern. Um die Daten zu ermitteln, kann der
|
||||
Klassen soll ermittelt werden und die Statistik"=Webseite um diese Daten erweitern. Um die Daten zu ermitteln, kann der
|
||||
Quellcode aus \ref{lst:persistence-context-statistics} verwendet werden.
|
||||
|
||||
\begin{lstlisting}[language=Java,caption={Persistence"=Kontext Statistik},label=lst:persistence-context-statistics]
|
||||
|
@ -112,11 +112,10 @@ 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. Hierfür wird eine \textit{Factory} eingebaut, die sich in die
|
||||
Verarbeitung der Seiten einhängt, und damit die Zeiten für das Ermitteln der Daten, das Zusammensetzen und das
|
||||
Render der Sicht aufgenommen werden können. Die Zeiten werden in die Log"=Datei des \textit{Glassfish}"=Servers
|
||||
hinterlegt und durch das Skript ausgewertet. Somit ist es einfach aufzuzeigen, an welcher Stelle der größte Teil
|
||||
der Verzögerung auftritt.
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
|
@ -124,16 +123,16 @@ 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
|
||||
diese viel schneller abgefragt werden können. Zusätzlich werden die cached queries überprüft ob diese eine Verbesserung
|
||||
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, das die Webseite immer vollständig gerendert vom Server an den Client übertragen wird.
|
||||
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
|
||||
durchschnittliche Laufzeit ermittelt. Aufgrund der Speicherprobleme, werden auch die Speicherbenutzung des
|
||||
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 Anhang \ref{ap:timing} zu finden.
|
||||
gestartet wurde. Das zugehörige Script ist im \autoref{ap:timing} zu finden.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
\label{ch:performance-checking}
|
||||
|
||||
Für die Untersuchung der Performance"=Probleme sollten einige Vorbereitungen getroffen werden. Dazu gehören die
|
||||
Konfigurationen des Servers und in welcher Art und Umfang Anpassungen für die Performance"=Messung an der Software
|
||||
Konfigurationen des Servers und in welcher Art und Umfang Anpassungen für die Performance"=Messungen an der Software
|
||||
durchgeführt werden müssen. Hierbei ist zu beachten, dass die Anpassungen minimal sind, damit die Messung selbst nicht
|
||||
das Ergebnis verfälscht. Zum Abschluss wird noch auf die Untersuchung der Abfragen eingegangen, wie diese im
|
||||
PostgreSQL"=Server durchgeführt wird.
|
||||
|
@ -34,22 +34,22 @@ Zusätzlich sollte noch die aktuelle Auslastung des Server überprüft werden.
|
|||
|
||||
Als Server wird hier ein Redhat"=Server mit der Standard"=Konfiguration des PostgreSQL"=Server 10 verwendet. Daher
|
||||
wird von einer richtigen Konfiguration der Speicher ausgegangen. Ebenfalls wird davon ausgegangen, dass der
|
||||
automatische Dienst für \textit{VACUUM} und \textit{ANALYZE} aktiv ist. Eine weitere Überprüfung des Servers ist nicht
|
||||
automatische Dienst für \texttt{VACUUM} und \texttt{ANALYZE} aktiv ist. Eine weitere Überprüfung des Servers ist nicht
|
||||
möglich, da kein Zugang zum aktuellen Produktionsservers möglich ist.
|
||||
|
||||
\section{Einbau und Aktivieren von Performance-Messung}
|
||||
\label{sec:performance-checking:performance-measure}
|
||||
|
||||
Um eine Messung der Performance in der Webseite durchführen zu können, gibt es in \ac{JSF} die Möglichkeit, über eine
|
||||
eigene Implementierung der Klasse \textbf{ViewDeclarationLanguageWrapper} sich in das generieren der Webseite
|
||||
einzuhängen. Hierbei können die Funktionen für das Erstellen, des Bauen und das Rendern der Webseite überschrieben
|
||||
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
|
||||
ausgewertet werden.
|
||||
|
||||
Zusätzlich wird noch eine Implementierung der zugehörigen Factory"=Klasse \textbf{ViewDeclarationLanguageFactory}
|
||||
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 \textbf{faces-config.xml} eingetragen, wie das in
|
||||
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.
|
||||
|
||||
\begin{lstlisting}[language=xml,caption={Einbindung Factory},label=lst:activate-factory]
|
||||
|
@ -76,10 +76,10 @@ log_rotation_size = 100MB
|
|||
\end{lstlisting}
|
||||
|
||||
Über die Konfiguration unter \autoref{lst:postgresql_logconf} wird definiert welche Werte protokolliert werden. Die
|
||||
wichtigste Einstellung ist \textit{log\_min\_duration\_statement}, diese definiert ab welcher Laufzeit eine Abfrage
|
||||
wichtigste Einstellung ist \texttt{log\_min\_duration\_statement}, diese definiert, ab welcher Laufzeit eine Abfrage
|
||||
protokolliert werden soll. Mit dem Wert 0 werden alle Abfragen protokolliert. Alle weitere Einstellungen sind so
|
||||
gesetzt, dass nicht unnötige Abfragen für die spätere Auswertung mit \textit{pgBadger} protokolliert werden.
|
||||
Zusätzlich ist die Einstellung \textit{log\_temp\_files} auf 0 zu setzen. Dadurch werden alle erzeugten temporären
|
||||
Zusätzlich ist die Einstellung \texttt{log\_temp\_files} auf 0 zu setzen, dadurch werden alle erzeugten temporären
|
||||
Dateien und ihre Größe ebenfalls protokolliert. Diese Dateien entstehen, wenn der temporäre Puffer für die Abfrage
|
||||
nicht ausreicht und die Zwischenergebnisse ausgelagert werden müssen.
|
||||
|
||||
|
@ -102,19 +102,19 @@ log_timezone = 'Europe/Berlin'
|
|||
\section{Prüfung von Abfragen}
|
||||
\label{sec:performance-checking:sql-query-checking}
|
||||
|
||||
Das untersuchen der protokollierten Abfragen auf Performance Optimierungen ist ein weiterer Bestandteil dieser Arbeit.
|
||||
Das Schlüsselwort \textbf{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 dem die Knoten die
|
||||
unterschiedlichen Zugriffsarten darstellt. Die Verbindung der Knoten und der Aufbau zeigt die Operationen, wie
|
||||
etwas Joins, Aggregierung und Sortierung, und die Reihenfolgen der Abarbeitung. Zusätzlich sind auch Zwischenschritte,
|
||||
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
|
||||
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
|
||||
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 \textit{ANALYZE} wird die Abfrage ausgeführt und die echten Werte und Laufzeiten angezeigt. Ohne dieser,
|
||||
wird nur der Plan erstellt und dargestellt. Durch \textit{VERBOSE} werden zusätzliche Informationen zum Abfrageplan
|
||||
mit dargestellt und mit \textit{BUFFERS} werden die Informationen über die Nutzung der Caches mit dargestellt. Um an
|
||||
Ende noch eine Zusammenfassung mit anzuhängen, gibt es die Option \textit{summary}. Eine vereinfachte Form des Aufrufs
|
||||
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
|
||||
ist in \autoref{lst:explain-easy} dargestellt.
|
||||
|
||||
\begin{lstlisting}[language=SQL,caption={Aufruf von EXPLAIN},label=lst:explain-easy]
|
||||
|
@ -122,36 +122,38 @@ EXPLAIN (ANALYZE, VERBOSE, BUFFERS, SUMMARY)
|
|||
select * from document;
|
||||
\end{lstlisting}
|
||||
|
||||
Die zwei bekanntesten Knotentypen sind \textit{Seq Scan} und \textit{Index Scan}. Beim \textit{Seq Scan} wird die
|
||||
Tabelle Zeile für Zeile gelesen und wenn vorhanden nach den Bedingungen gefiltert, hierbei entsteht eine unsortierte
|
||||
Liste, entsprechend sind die Startkosten niedrig. Die bessere Alternative ist der \textit{Index Scan}, bei dem der
|
||||
Index nach den Kriterien durchsucht wird, was meist durch den Aufbau des Index als BTree (Multi"=Way Balanced Tree)
|
||||
sehr schnell geht.
|
||||
\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
|
||||
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öglichkeiten sind die Verwendung von Indexe. Diese sind aber mit bedacht zu wählen, da bei
|
||||
Eine weitere Optimierungsmöglichkeit ist die Verwendung von Indexe. 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
|
||||
dessen Statistik muss regelmässig mit aktualisiert werden. Ebenfalls ist die Reihenfolge der Spalte in einem
|
||||
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 aufwendige Abfragen zu optimieren, bietet der PostgreSQL noch die Möglichkeiten von
|
||||
\textit{Materialized View}. Diese sind sehr ähnlich zu Sichten, speichern zusätzlich die Ergebnisse in einer
|
||||
tabellenähnlichen Form ab. Somit sind die Zugriff auf diese Daten häufig performanter als die eigentliche Abfrage.
|
||||
Die Performance wird durch die zusätzliche Aktualisierung des Datenbestand erkauft und muss daher abgewägt werden,
|
||||
was sinnvoller ist.
|
||||
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.
|
||||
Daher muss abgewägt werden, ob die Performance-Verbesserung trotz der zusätzliche 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 \textit{pg\_statistic} oder die lesbarere Systemsicht \textit{pg\_stats} die
|
||||
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 \textit{ANALYZE} beziehungsweise \textit{VACUUM ANALYZE} Kommando die Informationen zum Anteil der
|
||||
\textit{NULL}"=Werte (null\_frac), Durchschnittlichen Größe (avg\_width), unterschiedlicher Werte (n\_distinct) und
|
||||
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
|
||||
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 \textit{CREATE STATISTICS} erweitert werden, für einen besseren
|
||||
Abfrageplan. Das aktivieren der zusätzlichen Statistiken sollten immer in Verbindung mit dem überprüfung des
|
||||
Abfrageplans durchgeführt werden, um zu ermitteln ob die Anpassung zu einer Optimierung und keiner Verschlechterung
|
||||
führt.
|
||||
Diese Informationen können noch durch das Kommando \texttt{CREATE STATISTICS} erweitert werden, für einen besseren
|
||||
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.
|
||||
|
|
|
@ -3,45 +3,45 @@
|
|||
\chapter{Performance-Untersuchung der Anwendung}
|
||||
\label{ch:performance-investigation-application}
|
||||
|
||||
Nun werden die unterschiedlichen Schichten betrachtet und möglichen Performance"=Verbesserungen untersucht und deren
|
||||
Nun werden die unterschiedlichen Schichten betrachtet und mögliche Performance"=Verbesserungen untersucht und deren
|
||||
Vor"= und Nachteile herausgearbeitet.
|
||||
|
||||
Für die Tests wird ein aktuelles Manjaro-System mit frisch installierten Payara als Serverhost und der IntelliJ IDEA
|
||||
Für die Tests wird ein aktuelles Manjaro"=System mit frisch installierten Payara als Serverhost und der IntelliJ IDEA
|
||||
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 an dem 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 OutOfMemoryError protokolliert worden.
|
||||
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 und diese zeitgleich zu beobachten. Diese
|
||||
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
|
||||
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 OutOfMemoryError
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
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 der \autoref{tbl:measure-without-cache}.
|
||||
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
|
||||
ermitteln, auch hier gilt, dass weniger Aufrufe besser sind. Als letztes wird noch der verwendete Arbeitsspeicher
|
||||
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
|
||||
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.
|
||||
|
||||
Als Grundlage für die Vergleiche wurden eine Messung durchgeführt, bei der alle Caches deaktiviert wurden und keine
|
||||
Als Grundlage für die Vergleiche wurde eine Messung durchgeführt, bei welcher alle Caches deaktiviert wurden und keine
|
||||
Änderung am Code vorgenommen wurde. Das Ergebnis dieser Messung ist in \autoref{tbl:measure-without-cache} zu finden.
|
||||
Diese zeigen auch direkt ein erwartetes Ergebnis, dass der erste Aufruf bedeutend länger dauert als die Nachfolgenden.
|
||||
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 auch relative gleichmässig, was nicht recht ins Bild passt, da hier keine Objekte im Cache
|
||||
Der Speicherbedarf steigt relative gleichmässig, was nicht recht ins Bild passt, da hier keine Objekte im Cache
|
||||
gehalten werden sollten.
|
||||
|
||||
\begin{table}[!h]
|
||||
|
@ -62,7 +62,7 @@ gehalten werden sollten.
|
|||
\label{tbl:measure-without-cache}
|
||||
\end{table}
|
||||
|
||||
Vor jedem weiteren Test-Lauf wurde die Domain beendet und komplett neugestartet, um mit einer frischen Instanz zu
|
||||
Vor jedem weiteren Test"=Lauf wird die Domain beendet und komplett neugestartet, um mit einer frischen Instanz zu
|
||||
beginnen. Hierbei ist aufgefallen, dass fast immer 62 Abfragen zur Startup-Phase dazugehört haben, unabhängig von den
|
||||
konfigurierten Cache Einstellungen. Einige dieser Abfragen sind durch das Erstellen der \textit{Materialized View}
|
||||
\textit{searchreference} und \textit{searchfulltext} erklärbar. Zusätzlich ist noch ein zyklischer Dienst
|
||||
|
@ -71,22 +71,22 @@ und entsprechend einige Abfragen an die Datenbank absetzt. Da weder die Sichten
|
|||
benötigt werden, wurde der Dienst und das Erstellen im Code für die weiteren Tests deaktiviert.
|
||||
|
||||
Da die Abfragezeiten auf der Datenbank zu gering waren, um eine Verbesserung feststellen zu können, wurde für den
|
||||
PostgreSQL und den Payara-Server ein Docker-Container erzeugt und diese limitiert. Die Konfiguration ist im
|
||||
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 neue Messungen. Für den Speicherbedarf wird nun nicht mehr der benutzte
|
||||
Mit dem neuen Aufbau ergeben sich nun 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.
|
||||
|
||||
Für die Ausführungszeiten der SQL-Abfragen wurden nur die sechs Abfragen für die Darstellung der Tabelle beachtet.
|
||||
Für die Ausführungszeiten der \ac{SQL}"=Abfragen wurden nur die sechs Abfragen für die Darstellung der Tabelle beachtet.
|
||||
Hierzu zählt die Hauptabfrage der Dokumenten"=-Tabelle, die Ermittlung des letzten und ersten Eintrags in der Tabelle,
|
||||
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.
|
||||
zu laden, und in die Java"=Objekte umzuformen.
|
||||
|
||||
\begin{table}[h]
|
||||
\centering
|
||||
|
@ -112,11 +112,11 @@ zu laden, und in die Java-Objekte umzuformen.
|
|||
\section{Caching im OpenJPA}
|
||||
\label{sec:performance-investigation-application:caching-openjpa}
|
||||
|
||||
Die Cache-Einstellung von OpenJPA werden über die zwei Einstellungen \texttt{openjpa.DataCache} und
|
||||
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 Elementen im Cache gesteuert werden. Wird diese Anzahl erreicht, dann werden zufällige
|
||||
Objekte aus dem Cache entfernt und in eine SoftReferenceMap übertragen. Bei der Berechnung der Anzahl der Element werden
|
||||
\textit{CacheSize} die Anzahl der Elemente im Cache gesteuert werden. Wird diese Anzahl erreicht, dann 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
|
||||
|
@ -153,7 +153,7 @@ wachsenden Speicherbedarfs nur nicht erklärt werden.
|
|||
\label{tbl:measure-ojpa-active}
|
||||
\end{table}
|
||||
|
||||
Bei einer erhöhten Cache-Größe, von 1000 auf 10000, zeigt sich auf den ersten Blick ein noch besseres Bild ab, wie in
|
||||
Bei einer erhöhten Cache"=Größe, von 1000 auf 10000, zeigt sich auf den ersten Blick ein noch besseres Bild ab, wie in
|
||||
\autoref{tbl:measure-ojpa-active-bigger} ersichtlich ist. Der erste Aufruf entspricht der Laufzeit mit geringerer
|
||||
Cache"=Größe, aber schon die Anfragen an die Datenbank gehen drastisch zurück. Bei den weiteren Aufrufen werden im
|
||||
Schnitt nun nur noch 6 Anfragen pro Seitenaufruf an die Datenbank gestellt, wodurch die Laufzeit im Schnitt nochmal
|
||||
|
@ -213,11 +213,11 @@ der Objekte den Cache übersteigt, fällt die Verbesserung geringer aus.
|
|||
\section{Cached Queries}
|
||||
\label{sec:performance-investigation-application:cached-query}
|
||||
|
||||
Über die Einstellung \textit{openjpa.""jdbc.""QuerySQLCache} wird der Cache für abfragen aktiviert. Hierbei können
|
||||
Ü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
|
||||
die keine Parameter verwenden. Das sieht man auch entsprechend der Auswertung der Aufrufe in der
|
||||
\autoref{tbl:measure-cached-queries}, dass hier keine Veränderung der Aufrufzeiten stattgefunden hat. Gleich ob man
|
||||
mit \ac{JPQL} oder mit der Criteria API abfragt.
|
||||
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.
|
||||
|
||||
% document, documentaddresseeperson, first/last, documentcoauthorperson, count und documentfacsimile
|
||||
\begin{table}[h!]
|
||||
|
@ -247,7 +247,7 @@ mit \ac{JPQL} oder mit der Criteria API abfragt.
|
|||
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.
|
||||
Zusätzlich dazu sind die Konfiguration \textit{openjpa.""QueryCache}, \textit{openjpa.""DataCache} und
|
||||
\textit{openjpa.""DataCacheManager} auf \textit{ehcache} anzupassen. Anhand der Annotation \textbf{@DataCache} kann
|
||||
\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
|
||||
|
@ -255,10 +255,10 @@ Cache"=Manager aktiviert werden, dieser kann entweder durch Code programmiert we
|
|||
in der \textit{ehcache.xml}.
|
||||
|
||||
Anhand der Auswertung von \ref{tbl:measure-ehcache-active} sieht man, dass der Ehcache einen starke Performance
|
||||
Verbesserung aufbringt. Über die Performance"=Statistik"=Webseite kann beobachtet werden, dass bei gleichen Aufruf
|
||||
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. Zusätzlich zeigt sich,
|
||||
das sich die Abfragezeiten in der Datenbank nur gering verkürzt wurden, aber die Laufzeit der Webseite sich starkt
|
||||
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
|
||||
verbessert hat. Dies lässt auch hier den Schluss zu, dass die Erstellung der Objekte im OpenJPA die meiste Zeit
|
||||
benötigt.
|
||||
|
||||
|
@ -288,13 +288,13 @@ benötigt.
|
|||
\section{Caching in EJB}
|
||||
\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
|
||||
Größen des Pools definiert werden. Ebenso wird an dieser Stelle die maximale Größe des Caches und die Größe der
|
||||
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
|
||||
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. Und es ist ersichtlich, dass die Anzahl der Datenbankabfragen nicht reduziert
|
||||
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
|
||||
den Controller bereitgestellt werden. Die Objekt selbst werden nicht im \ac{EJB}"=Cache hinterlegt.
|
||||
|
||||
|
@ -316,7 +316,7 @@ den Controller bereitgestellt werden. Die Objekt selbst werden nicht im \ac{EJB}
|
|||
\hline
|
||||
\end{tabular}
|
||||
}
|
||||
\caption{Messung mit \ac{EJB}-Cache}
|
||||
\caption{Messung mit EJB"=Cache}
|
||||
\label{tbl:measure-ejb-cache-active}
|
||||
\end{table}
|
||||
|
||||
|
@ -324,7 +324,7 @@ den Controller bereitgestellt werden. Die Objekt selbst werden nicht im \ac{EJB}
|
|||
\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
|
||||
Dokumentenliste wird der Code aus dem \autoref{lst:jpql-document-list-jpql} verwendet. Die Namen mit vorangestellten
|
||||
Dokumentenliste wird der Code aus \autoref{lst:jpql-document-list-jpql} verwendet. Die Namen mit vorangestellten
|
||||
Doppelpunkt sind Übergabevariablen.
|
||||
|
||||
\begin{lstlisting}[language=Java,caption={JPQL Dokumentenliste},label=lst:jpql-document-list-jpql]
|
||||
|
@ -359,45 +359,46 @@ if(myResultList != null && !myResultList.isEmpty()) {
|
|||
Da dieser Code direkt so aus dem Projekt kommt, wird hierfür keine gesonderte Zeitmessung durchgeführt, da diese der
|
||||
Messung aus \autoref{tbl:measure-without-cache} entspricht.
|
||||
|
||||
Für die Optimierung wurden noch zusätzlich die Hints \textit{openjpa.""hint.""OptimizeResultCount},
|
||||
\textit{javax.""persistence.""query.""fetchSize} und \textit{openjpa.""FetchPlan.""FetchBatchSize} gesetzt. Hierbei
|
||||
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.
|
||||
|
||||
Ebenso bringt der Hint \textit{openjpa.""FetchPlan.""ReadLockMode} auch keinen Unterschied bei der Geschwindigkeit.
|
||||
Hierbei ist erklärbar, da im Standard bei einer reinen Selektion eine Lesesperre aktiv sein muss.
|
||||
Bei \textit{openjpa.""FetchPlan.""Isolation} wird gesteuert, auf welche Sperren beim laden geachtet wird. Damit könnte
|
||||
man zwar schreibsperren umgehen, und würde damit die Anfrage nicht mehr blockieren lassen, aber es führt unweigerlich
|
||||
zu sogenannten \glqq Dirty"=Reads\grqq, wodurch die Ausgabe verfälscht werden könnte. Daher ist diese Einstellung sehr
|
||||
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.
|
||||
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
|
||||
mit Vorsicht zu verwenden.
|
||||
|
||||
Mit dem Hint \textit{openjpa.""FetchPlan.""EagerFetchMode} wird definiert, wie zusammengehörige Objekte abgefragt werden.
|
||||
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 \glqq to-one\grqq"=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
|
||||
\glqq to-one\grqq"=Relation funktioniert das rekursive und spart sich damit einige einzelne Abfragen.
|
||||
Bei der Einstellung \textit{parallel} wird für zwar für jedes abhängigen Objektdefinition eine Abfrage durchgeführt,
|
||||
aber bei dieser wird der Einstieg über das Hauptobjekt durchgeführt. 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 WHERE"=Abfrage nochmal durchgeführt und um
|
||||
die JOINS ergänzt, um die Daten der Unterobjekte zu ermitteln.
|
||||
Mit dem Hint \textit{openjpa.""FetchPlan.""SubclassFetchMode} ist die Konfiguration für Unterklassen definiert. Die
|
||||
Möglichkeiten entsprechen der vom \textit{openjpa.""FetchPlan.""EagerFetchMode}.
|
||||
>>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
|
||||
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
|
||||
der abhängigen Daten und das zusammensetzen in der OpenJPA-Schicht.
|
||||
|
||||
Der letzte Hint \textit{openjpa.""FetchPlan.""MaxFetchDepth} schränkt die rekursive Tiefe ein, für die abhängige
|
||||
Der letzte Hint \texttt{openjpa.""FetchPlan.""MaxFetchDepth} schränkt die rekursive Tiefe ein, für die abhängige
|
||||
Objekte mitgeladen werden. Lediglich auf Grund fehlender Datenbestände wird die Abfrage beschleunigt.
|
||||
|
||||
\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 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 durchführen muss nun nur noch Datenklasse angegeben werden 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]
|
||||
|
@ -427,7 +428,7 @@ 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 anschaut, sieht man auch, dass die zusammengesetzten
|
||||
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.
|
||||
|
||||
\begin{table}[h!]
|
||||
|
@ -456,21 +457,21 @@ Implementierung ohne bedenken gegeneinander ausgetauscht werden, und die verwend
|
|||
einfacher umzusetzen ist.
|
||||
|
||||
Bei den Hints ist es das gleiche wie bei \ac{JPQL}. Auch hier haben die meisten Hints keinen merkbaren Einfluss. Die
|
||||
Einstellung \textit{openjpa.""FetchPlan.""EagerFetchMode} liefert auch hier Optimierungen, wenn der Wert auf
|
||||
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.
|
||||
|
||||
\section{Materialized Views}
|
||||
\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
|
||||
\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
|
||||
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
|
||||
|
@ -586,7 +587,7 @@ CREATE INDEX idx_searchdocument_documentcategory
|
|||
\end{lstlisting}
|
||||
|
||||
Für die Datenermittlung wurden die notwendigen Teile aus dem Wedekind"=Projekt kopiert. Bei der Darstellung wurden die
|
||||
vorhanden Elemente die die Liste der Dokumente anzeigt kopiert und auf die \textit{SearchDocument}"=Klasse angepasst.
|
||||
vorhanden Elemente, welche die Liste der Dokumente anzeigt, kopiert und auf die \texttt{SearchDocument}"=Klasse angepasst.
|
||||
|
||||
% document, first/last, documentaddresseeperson, documentcoauthorperson, documentfacsimile und count
|
||||
% document, count, first/last
|
||||
|
@ -614,13 +615,13 @@ vorhanden Elemente die die Liste der Dokumente anzeigt kopiert und auf die \text
|
|||
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
|
||||
der Speicheranstieg weniger stark aus. Die Verbesserung der Aufrufzeiten lässt sich zusätzlich erklären, dass hier nun
|
||||
nur noch vier statt der 6 Abfragen an die Datenbank gestellt werden, da die Einzelabfragen für die Adressen der
|
||||
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 wurde. Da die Sicht nun explizit für dies Anfrage geschaffen wurde, wurde die Bedingungen nun direkt in die
|
||||
benötigt wurden. Da die Sicht nun explizit für dies 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.
|
||||
\autoref{lst:sql-materialized-view-ext} und das Entfernen der Parameter aus dem SQL"=Anfragen im Java"=Code.
|
||||
|
||||
\begin{lstlisting}[language=SQL,caption={SQL Materialized View Erweiterung},label=lst:sql-materialized-view-ext]
|
||||
WHERE d.validuntil > NOW()
|
||||
|
@ -628,7 +629,7 @@ AND d.ispublishedindb = true;
|
|||
\end{lstlisting}
|
||||
|
||||
Nach dem Anpassungen haben sich dann die Werte aus \autoref{tbl:measure-materialized-view-ext} ergeben. Diese Werte
|
||||
zeigen nur minimale Unterschiede in den Zeiten, was auf Messtoleranzen zurückzuführen ist.
|
||||
zeigen nur minimale Unterschiede in den Zeiten, diese sind auf Messtoleranzen zurückzuführen.
|
||||
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
|
@ -651,34 +652,35 @@ zeigen nur minimale Unterschiede in den Zeiten, was auf Messtoleranzen zurückzu
|
|||
\label{tbl:measure-materialized-view-ext}
|
||||
\end{table}
|
||||
|
||||
Da bei der \textit{Materialized View} das laden der Daten und das wandeln in die Java"=Objekte getrennt programmiert
|
||||
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
|
||||
\textit{map}"=Aufruf und der \textit{map}"=Aufruf gemessen. Für den ersten Aufruf, wurde ein \textit{SearchDocument}
|
||||
Objekt erzeugt und immer diese Objekt zurückgegeben. Damit wurde erst mal überprüft, wie lange das ermitteln der Daten
|
||||
und das durcharbeiten der Ergebnisse bestimmt. Hierbei lagen die Zeiten bei circa 1 ms für das reine Datenladen und 3 ms
|
||||
für den Aufruf der \textit{map}"=Funktion. Sowie innerhalb der \textit{map}"=Funktion pro Eintrag ein Objekt
|
||||
erzeugt, noch ohne eine Konvertierung der ermittelten Daten in das Objekt, steigt die Laufzeit schon auf 54 ms.
|
||||
Wenn man nun noch die Konvertierung der Daten wieder einbaut, steigt die Laufzeit nochmal auf nun 82 ms.
|
||||
Dies zeigt, alleine das erzeugen der Objekt und der Json"=Parse Aufruf kostet die meiste Zeit.
|
||||
\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}
|
||||
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.
|
||||
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 \textit{openjpa.""FetchPlan.""FetchBatchSize} kann die Abfrage enorm verschlechtern. Wenn
|
||||
Bei der Verwendung des Hints \texttt{openjpa.""FetchPlan.""FetchBatchSize} kann 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 \textit{map}"=Funktion wird dadurch verlängert.
|
||||
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
|
||||
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.
|
||||
Dies ist dadurch erklärbar, da keine Objekte durch das OpenJPA"=Framework erstellt werden, sondern erst in der
|
||||
\textit{map}"=Funktion des eigenen Codes und daher wird der Cache nicht genutzt.
|
||||
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.
|
||||
|
||||
Wie schon ermittelt, benötigt das erstellen der Objekte den Großteil der Zeit für die Datenermittlung. Aufgrund dessen
|
||||
wurde die übernommen \textit{SearchDocument}"=Klasse nochmal genauer betrachtet. Beim erstellen, werden die
|
||||
Wie schon ermittelt, benötigt das Erstellen der Objekte den Großteil der Zeit für die Datenermittlung. Auf Grund dessen
|
||||
wurde die übernommene \texttt{SearchDocument}"=Klasse abermals genauer betrachtet. Beim Erstellen werden die
|
||||
\textit{Json}"=Daten direkt in Java"=Objekte gewandelt. Im ersten Schritt wird die Parse"=Funktion entfernt und die
|
||||
Seite nochmals aufgerufen. Durch diese Umstellung fällt die Laufzeit der Datenermittlung auf circa 4 ms ab. Nun muss
|
||||
noch geprüft werden, welche Zeit nun der Client zum parsen der \textit{Json}"=Daten benötigt. Hierfür werden die
|
||||
Daten in einem versteckten \textbf{span}"=Element hinterlegt, wie es im \autoref{lst:jsf-datatable-json} zu sehen ist.
|
||||
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
|
||||
\textbf{ajax}"=Element im Beispiel ist notwendig, damit bei einem Seitenwechsel die gleiche Interpreter"=Funktion für
|
||||
\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.
|
||||
|
||||
\begin{lstlisting}[language=xml,caption={DataTable mit Json},label=lst:jsf-datatable-json]
|
||||
|
@ -694,10 +696,10 @@ 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 ie übertragenen
|
||||
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}
|
||||
ermittelt erst alle versteckten Elemente, parsed den Inhalt und erstellt neue \textit{HTML}"=Elemente mit dem
|
||||
darzustellenden Inhalt. Zusätzlich wird noch eine Zeitmessung mit eingebaut, um die Laufzeit am Client für das Rendern
|
||||
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.
|
||||
|
||||
\begin{lstlisting}[language=javascript,caption={Wandeln von Json nach Html},label=lst:jsf-datatable-json-convert]
|
||||
|
@ -741,16 +743,16 @@ $(document).ready(function() {
|
|||
});
|
||||
\end{lstlisting}
|
||||
|
||||
Da nun am Client Code ausgeführt wird, nachdem die Daten übertragen wurden, kann nicht mehr alles über das Script
|
||||
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. Dies bedeutet addiert kommt man mit dieser
|
||||
Lösung auf eine kürzere Laufzeit und weniger Last am Server.
|
||||
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}
|
||||
|
||||
\section{Optimierung der Abfrage}
|
||||
\label{sec:performance-investigation-application:optimizing-query}
|
||||
|
||||
Für die Optimierung der Abfrage werden diese zuerst mit \textit{explain}, wie in \autoref{lst:explain-diagnostic}
|
||||
dargestellt, untersuchen. Für die einfachere Diagnose, wird der erstellte Plan mit Hilfe von
|
||||
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
|
||||
\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]
|
||||
|
@ -773,7 +775,7 @@ limit 400;
|
|||
|
||||
Die erstellte Visualisierung der Abfrage ist in \autoref{fig:explain-visualize} zu sehen. In der Visualisierung wurde
|
||||
die Darstellung der Kosten gewählt, da ein Vergleich auf Basis der Zeit sehr schwierig ist und von äußeren Faktoren
|
||||
abhängt, wie zum Beispiel dem Cache. Die Kosten sind stabiler und hängen in erster Linie vom Datenbestand ab.
|
||||
abhängt, wie zum Beispiel dem Cache. Die Kosten sind stabiler und hängen in erster Linie von der Art des Datenbestandes ab.
|
||||
|
||||
\begin{figure}[h!]
|
||||
\includegraphics[width=\linewidth]{gfx/chapter05_ExplainVisualize.png}
|
||||
|
@ -782,19 +784,19 @@ abhängt, wie zum Beispiel dem Cache. Die Kosten sind stabiler und hängen in er
|
|||
\end{figure}
|
||||
|
||||
In der Graphik ist zu sehen, dass zum einen die Hauptkosten im untersten Knoten \textit{Seq Scan} und einen der
|
||||
obersten Knoten dem \textit{HashAggregate} liegen. Zusätzlich sieht man anhand der stärke von den Verbindungslinien der
|
||||
Knoten, dass die Menge der Datensätze enorm hoch ist und dieser sich bis zum obersten Knoten durchzieht. Dies
|
||||
obersten Knoten dem \textit{HashAggregate} liegen. Zusätzlich sieht man anhand der Stärke von den Verbindungslinien der
|
||||
Knoten, dass die Menge der Datensätze enorm hoch ist und diese sich bis zum obersten Knoten durchziehen. Dies
|
||||
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, dass der komplette Scan der Tabelle kostengünstiger ist, als
|
||||
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
|
||||
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 dann ein
|
||||
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
|
||||
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
|
||||
\textit{order by} innerhalb eines Sub"=Selects nicht erlaubt ist, verwenden wir hierfür eine \textit{Common Table
|
||||
\texttt{order by} innerhalb eines Sub"=Selects nicht erlaubt ist, verwenden wir hierfür eine \textit{Common Table
|
||||
Expression}, wie es in \autoref{lst:explain-optimize-cte} zu sehen ist. Zusätzlich wurde noch ein Index auf der
|
||||
\textit{document}"=Tabelle für die Spalten der Bedingung und der Sortierung gesetzt, wie in
|
||||
\autoref{lst:explain-optimize-cte-idx} zur sehen, damit in der \textit{Common Table Expression} nur der Index verwendet
|
||||
|
@ -821,9 +823,9 @@ create index idx_document_with_stmt on document using btree
|
|||
, startday desc, id );
|
||||
\end{lstlisting}
|
||||
|
||||
Mit diesen Umstellungen erkennt man nun, dass die Kosten entsprechend gefallen sind. Ebenfalls konnten die Laufzeit um
|
||||
Mit diesen Umstellungen erkennt man, dass die Kosten entsprechend gefallen sind. Ebenfalls konnten die Laufzeit um
|
||||
mehr als den Faktor drei reduziert werden. Die Optimierung ist in \autoref{fig:explain-visualize-with} sehr deutlich
|
||||
an dein dünneren Verbindungslinien zwischen den Knoten und der Umstellung von einigen \textit{Seq Scan} zu
|
||||
an den dünneren Verbindungslinien zwischen den Knoten und der Umstellung von einigen \textit{Seq Scan} zu
|
||||
\textit{Index Scan} ersichtlich. Zeitgleich ist auch der teure \textit{HashAggregate} nicht mehr im Abfrageplan
|
||||
vorhanden.
|
||||
|
||||
|
@ -834,7 +836,7 @@ vorhanden.
|
|||
\end{figure}
|
||||
|
||||
Bei der Untersuchung der Abfrage zur \textit{Materialized View} ist direkt herausgekommen, dass hier keine Optimierung
|
||||
mehr möglich ist, da durch die definierten Index bei den aktuell möglichen Sortierkriterien direkt ein
|
||||
mehr möglich ist, da durch die definierten Indexe bei den aktuell möglichen Sortierkriterien direkt ein
|
||||
\textit{Index Scan} verwendet wird. Dies ist durch eine Überprüfung der Abfragepläne beweisbar, für diesen Fall wird
|
||||
die Abfrage aus \autoref{lst:explain-search-document} verwendet.
|
||||
|
||||
|
@ -850,10 +852,10 @@ limit 400;
|
|||
\end{lstlisting}
|
||||
|
||||
Der dazugehörige Abfrageplan ist in \autoref{lst:explain-search-document-output} zu sehen, hierbei ist die erste
|
||||
Ausgabe mit dem erstellten Index und vor der zweiten Ausgabe wurde der Index deaktiviert. Anhand der Ausgabe ist zu
|
||||
Ausgabe mit dem erstellten Index. Vor der zweiten Ausgabe wurde dieser Index deaktiviert. Anhand der Ausgabe ist zu
|
||||
sehen, dass bei der Verwendung des Index weniger Operation notwendig sind und damit auch die teure Sortierung
|
||||
eingespart werden konnte. Dies liegt daran, dass der Index entsprechend des Sortierkriterien definiert wurde Und
|
||||
somit es möglich ist, direkt in den Index die Elemente in der richtigen Reihenfolge zu ermitteln.
|
||||
eingespart werden konnte. Dies liegt daran, dass der Index entsprechend des Sortierkriterien definiert wurde und
|
||||
somit ist es möglich, direkt in dem Index die Elemente in der richtigen Reihenfolge zu ermitteln.
|
||||
Somit ist durch den Index der schnellstmögliche Zugriff gegeben.
|
||||
|
||||
\begin{lstlisting}[basicstyle=\scriptsize,caption={aa},label=lst:explain-search-document-output]
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
|
||||
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.
|
||||
der Effektivität mit beachtet. \mytodos{verena}
|
||||
|
||||
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 welchen Umfang
|
||||
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
|
||||
|
@ -31,14 +31,14 @@ 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.
|
||||
Dies ist in diesem Fall nicht anwendbar, da nicht nur 1:n Beziehungen vorhanden sind, sondern auch auch n:m Beziehungen.
|
||||
Dadurch würden sich die Anzahl der Dokumentenliste erhöhen. Eine weitere Möglichkeit wäre es, die Duplikate auf der
|
||||
Dadurch würde sich die Anzahl der Dokumentenliste erhöhen. Eine weitere Möglichkeit wäre es, die Duplikate auf der
|
||||
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
|
||||
funktionieren in statischen Webseiten aber keine Suchen oder eine Sortierungen. Die Sortierung könnte durch das Erstellen
|
||||
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
|
||||
werden können.
|
||||
|
@ -65,9 +65,9 @@ die notwendige Rechenleistung fehlt, um die Webseite in annehmbarer Zeit darzust
|
|||
|
||||
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 und die zum
|
||||
Client übertragene Datenmenge ist auch geringer. Dadurch benötigt die Seite auf dem Client auch weniger Zeit zum
|
||||
rendern.
|
||||
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
|
||||
Zeit zum rendern.
|
||||
|
||||
Da das Paging für den Fall der Dokumentenliste implementiert ist, gibt es hier keine weiteren offensichtliche
|
||||
Optimierungsmöglichkeiten.
|
||||
|
@ -85,7 +85,7 @@ Das Entfernen der Objekte kann zwar umgangen werden, indem die häufig abgefragt
|
|||
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
|
||||
Grenzwert aufbaut und dann nicht mehr entleeren wird. Gerade bei kleiner dimensionierten Servern stellt dies ein
|
||||
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. Dies ist der Grund warum diese Anfragen in diesem Cache nicht gespeichert werden.
|
||||
werden. Aus diesem Grund werden die Anfragen in diesem Cache nicht gespeichert werden.
|
||||
|
||||
Dadurch ist dieser Cache für eine Performance"=Verbesserung in dem Fall der Dokumentenliste nicht anwendbar.
|
||||
|
||||
|
@ -129,7 +129,7 @@ des OpenJPA Framework liegen muss.
|
|||
|
||||
Durch die effizienter 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, was direkt am verfügbaren Arbeitsspeicher abhängt.
|
||||
bereitgestellt werden kann, dies hängt direkt vom verfügbaren Arbeitsspeicher ab.
|
||||
|
||||
\section{Caching in EJB}
|
||||
\label{sec:evaluation:ejb}
|
||||
|
@ -154,7 +154,7 @@ von OptimizeResultCount, der FetchSize sowie der FetchBatchSize hilft dem Framew
|
|||
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
|
||||
ermittelt werden. Bei Umstellung auf \textit{parallel} konnte für die Ermittlung der Dokumente einiges an Performance gewonnen
|
||||
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.
|
||||
|
@ -164,7 +164,7 @@ Auf Grund dessen ist die Entscheidung der Technik für die Performance irrelevan
|
|||
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
|
||||
ausgegangen werden kann. Gerade bei ein größeren Anzahl lohnt es sich den Hint auf \textit{parallel} zu setzen.
|
||||
ausgegangen werden kann. Gerade bei einer größeren Anzahl lohnt es sich den Hint auf \textit{parallel} zu setzen.
|
||||
Gleiches gilt dem Hint SubclassFetchMode, dieser steuert dimensionierte Abfragen im Falle von abgeleiteten Klassen.
|
||||
|
||||
\section{Materialized View}
|
||||
|
@ -173,9 +173,9 @@ 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
|
||||
zurückgegeben. Der größte Nachteil der \textit{Materialized View} ist, das bei einer Änderung an den Quelldaten die
|
||||
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, noch selten Änderungen erfahren. Die Recherche über den Datenbestand die größte Zeit
|
||||
Briefe einmalig eingepflegt wurden, nur noch selten Änderungen erfahren. Die Recherche über den Datenbestand die größte Zeit
|
||||
gewidmet wird.
|
||||
|
||||
Ein weiterer Nachteil der \textit{Materialized View} ist die doppelte Speicherung der Daten, da die Daten für die Sicht
|
||||
|
@ -185,12 +185,12 @@ die Faksimile, sind nicht in dieser Sicht enthalten und werden erst beim Anzeige
|
|||
Zusätzlich ist zu beachten, dass bei der Verwendung eines Caches die Daten ebenfalls doppelt gehalten werden und in
|
||||
den meisten Fällen im Arbeitsspeicher gehalten werden.
|
||||
|
||||
Eine weitere Optimierung, welche durch die \textit{Materialized View} entstanden ist, ist die direkte integration der
|
||||
Eine weitere Optimierung, welche durch die \textit{Materialized View} entstanden ist, ist die direkte Integration der
|
||||
Autoren, der Koautoren und der Adressen im \textit{Json}"=Format. Durch diese aus dem Wedekind-Projekt übernommene Idee
|
||||
konnten schon viele zusätzliche Abfragen eingespart werden, da diese nicht mehr durch OpenJPA nach der Hauptabfragen
|
||||
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
|
||||
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
|
||||
schwächeren Clients in kurzer Zeit durchführbar.
|
||||
|
@ -200,17 +200,17 @@ verwendet wird. Der größte Unterschied zur Standardimplementierung ist die Ver
|
|||
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.
|
||||
|
||||
Zusammenfassend ist zu sagen, dass die \textit{Materialized View} eine gute Wahl sind, um die Listendarstellungen
|
||||
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
|
||||
Ressourcennutzung verringert wird. Zum anderen wird die Ressourcennutzung des Servers noch weiter reduziert, wenn die
|
||||
\textit{Json}"=Verarbeitung an den Client ausgelagert wird.
|
||||
Durch die doppelte Datenhalten muss bei jeder Abfrage geprüft werden, ob der Nutzung der \textit{Materialized View} sinnvoll
|
||||
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
|
||||
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 dadurch wird ein Zugriff auf so ein Objekt wieder
|
||||
langsamer. Somit ist die Optimierung über die \textit{Materialized View} auf langezeit gesehen kostengünstiger und
|
||||
und wirft alte Objekte aus dem Cache. Wenn dieser voll ist und 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.
|
||||
|
||||
\section{Optimierung der Abfrage}
|
||||
|
@ -219,7 +219,7 @@ stabiler.
|
|||
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
|
||||
gelöst werden. Bei größeren Abfragen mit mehreren Joins kann durch geschicktes umstellen die Performance verbessert
|
||||
werden. Die Hauptabfrage der Dokumentenliste ist eine mit mehreren Joins, und diese wurde explizit untersucht.
|
||||
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
|
||||
|
@ -233,9 +233,9 @@ Zeilenanzahl während der Verarbeitung enorm verringert werden, wodurch einige d
|
|||
umgestellt wurden. Durch die Umstellung konnte die Abfragezeit um mehr als das dreifache reduziert wurde.
|
||||
|
||||
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
|
||||
mehrere Tabellen besteht. Das Wichtigste hierbei ist, dass die Bedingungen und die Sortierkriterien auf der
|
||||
Haupttabelle arbeiten. Wenn dem nicht so ist, müssen Joins in die \textit{Common Table Expression} mit aufgenommen
|
||||
werden und damit funktioniert die Reduzierung der Datensätze nicht mehr. Bei der Selektion einer Tabelle hat diese Art
|
||||
der Optimierung keine Auswirkung, hier hilft nur das geschickte setzen von Indexen auf die Tabelle, welche die
|
||||
der Optimierung keine Auswirkung, hier hilft nur das geschickte Setzen von Indexen auf die Tabelle, welche die
|
||||
Bedingungen und die Sortierkriterien beinhalten. Dies wurde mit der Untersuchung der Abfrage auf die
|
||||
\textit{Materialized View} bestätigt.
|
||||
|
|
|
@ -10,18 +10,18 @@
|
|||
% In der Gegenwart schreiben, außer bei verweisen auf die Arbeit, dann in der Vergangenheit!
|
||||
|
||||
Die Untersuchungen am Beispiel des Wedekind"=Projektes zeigen, dass mehrere Optimierungsmöglichkeiten in den
|
||||
Briefedition existieren. Für die Untersuchung wurde sich auf die Dokumentenliste beschränkt und anhand dieser
|
||||
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
|
||||
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
|
||||
%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.
|
||||
|
||||
Die Methode der Nutzerumfrage wurde nicht weiterverfolgt, da diese aufgrund zu wenigen Bedienern nicht zielführend war.
|
||||
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 wurde auf Grund von technischen Einschränkungen nicht weiterverfolgt.
|
||||
|
@ -34,7 +34,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 messbar. Ab dem Zeitpunkt, dass Objekte aus dem Cache entfernt werden müssen,
|
||||
speichern, sind die Verbesserung 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
|
||||
|
@ -51,13 +51,13 @@ durch die Umstellung der Ermittlung der unterlagerten Daten durch Hints eine Opt
|
|||
bezweckt das die unterlagerten Daten nicht einzeln für jede Zeile ermittelt wurde, 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
|
||||
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
|
||||
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.
|
||||
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 visuell Darstellung
|
||||
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
|
||||
|
@ -72,11 +72,11 @@ des Servers.
|
|||
\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
|
||||
Server durchführbar. Auf diese Weise könnten zusätzlich die Ressourcen am Server reduziert werden, beziehungsweise mit
|
||||
Möglichkeiten für eine Optimierungen zu lassen. 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önne durch Umstellung der Abfragen und der Optimierung des ORM"=Mappers umgesetzt
|
||||
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.
|
||||
|
||||
|
|
BIN
expose.pdf
BIN
expose.pdf
Binary file not shown.
|
@ -25,7 +25,7 @@
|
|||
\newcommand{\myUni}{FernUniversit\"at in Hagen\xspace}
|
||||
\newcommand{\mySubjectArea}{Lehrgebiet Datenbanken und Informationssysteme\xspace}
|
||||
\newcommand{\myLocation}{Höchstadt\xspace}
|
||||
\newcommand{\myTime}{21. August 2024\xspace}
|
||||
\newcommand{\myTime}{29. September 2024\xspace}
|
||||
\newcommand{\myVersion}{version 1.0\xspace}
|
||||
|
||||
% ****************************************************************************************************
|
||||
|
@ -61,3 +61,8 @@
|
|||
% \definecolor{Black}{cmyk}{0, 0, 0, 0}
|
||||
\definecolor{Black}{HTML}{221E1F} % Definition von https://en.wikibooks.org/wiki/LaTeX/Colors
|
||||
\definecolor{Green}{HTML}{00A64f}
|
||||
|
||||
% Farbiges Markieren mit \texthl{...}
|
||||
\usepackage{soul}
|
||||
% ToDos erstellen mit \todo{...}
|
||||
\usepackage{todonotes}
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
lineArrow/.style={arrows={-Latex[length=5pt 3 0]}},
|
||||
every fit/.style={inner sep=.4em,draw}
|
||||
]
|
||||
\node (browser) [block] {WebBrowser};
|
||||
\node (browser) [block] {Webbrowser};
|
||||
\node (fitClient) [rounded corners,fit=(browser)] {};
|
||||
\node [left] at (fitClient.west) {Client};
|
||||
|
||||
|
|
BIN
thesis.pdf
BIN
thesis.pdf
Binary file not shown.
Loading…
Reference in a new issue