% !TeX root = ../../thesis.tex \chapter{Performance-Untersuchung} \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"=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. \section{Überprüfung des Servers} \label{sec:performance-checking:server-checking} Die einfachste Art die Einstellungen am PostgreSQL"=Server zu überprüfen, ist die Abfrage von \ref{lst:postgresql-select-settings} am Datenbankserver auszuführen. \begin{lstlisting}[language=SQL,caption={Ermitteln der PostgreSQL Einstellungen},label=lst:postgresql-select-settings] SELECT name AS setting_name , setting AS setting_value , unit AS setting_unit FROM pg_settings WHERE name IN ( 'shared_buffers' , 'temp_buffers' , 'work_mem' , 'max_connections' , 'maintenance_work_mem' , 'autovacuum' ) \end{lstlisting} 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 \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 \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 \texttt{ViewDeclarationLanguageFactory} benötigt. Durch diese Factory"=Klasse wird der eigentlichen Wrapper mit der Performance-Messung in die Bearbeitungsschicht eingehängt. Diese Implementierung wird dann noch in der \texttt{faces-config.xml} eingetragen, wie das in \autoref{lst:activate-factory} aufgezeigt wird, damit die Factory durch das System aufgerufen wird. \begin{lstlisting}[language=xml,caption={Einbindung Factory},label=lst:activate-factory] de.wedekind.utils.VdlLoggerFactory \end{lstlisting} Der Quellcode der Klassen ist in \autoref{ap:jsf_performance_measure} zu finden. Um die Abfragen im \textit{PostgreSQL} untersuchen zu können, ist es am einfachsten, wenn man die Konfiguration so anpasst, dass alle Abfragen mit entsprechenden Zeitmessungen in die Log"=Datei ausgegeben werden. Über die Einstellungen in \autoref{lst:postgresql_logfile} wird die Datei und das Format der Ausgabe definiert. \begin{lstlisting}[language=yaml,caption={PostgreSQL Dateikonfiguration},label=lst:postgresql_logfile] log_destination = 'jsonlog' logging_collector = on log_directory = 'log' log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' log_file_mode = 0640 log_rotation_size = 100MB \end{lstlisting} Über die Konfiguration unter \autoref{lst:postgresql_logconf} wird definiert welche Werte protokolliert werden. Die 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 \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. \begin{lstlisting}[language=yaml,caption={PostgreSQL Ausgabekonfiguration},label=lst:postgresql_logconf] log_min_duration_statement = 0 log_autovacuum_min_duration = 10 log_checkpoints = off log_connections = on log_disconnections = on log_disconnections = on log_duration = off log_error_verbosity = default log_hostname = on log_lock_waits = on log_statement = 'none' log_temp_files = 0 log_timezone = 'Europe/Berlin' \end{lstlisting} \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 \texttt{EXPLAIN} ist im PostgreSQL vorhanden, um den Abfrageplan einer Abfrage zu ermitteln und darzustellen, um diese anschließend zu untersuchen. Der Abfrageplan ist als Baum dargestellt, bei welchem die Knoten die unterschiedlichen Zugriffsarten darstellen. Die Verbindung der Knoten und der Aufbau zeigt die Operationen, wie etwa Joins, Aggregierung und Sortierung, und die Reihenfolgen der Abarbeitung. Zusätzlich sind auch Zwischenschritte wie Zwischenspeicherungen ersichtlich. Zu jeder Operation gibt es neben dem Typ noch zusätzliche Informationen, wie die geschätzten Anlauf"= und Gesamtkosten (\textit{costs}), die geschätzte Anzahl der Zeilen (\textit{rows}) und die geschätzte Breite jeder Zeile (\textit{width}). Der Wert von \textit{costs} wird bei übergeordneten Knoten summiert. Bei der Option \texttt{ANALYZE} wird die Abfrage ausgeführt und die echten Werte und Laufzeiten angezeigt. Ohne diese 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] EXPLAIN (ANALYZE, VERBOSE, BUFFERS, SUMMARY) select * from document; \end{lstlisting} Die zwei bekanntesten Knotentypen sind \texttt{Seq Scan} und \texttt{Index Scan}. Wenn eine Tabelle Zeile für Zeile gelesen wird, zeigt der Abfrageplan einen \texttt{Seq Scan}"=Knoten an. Hierbei entsteht, unabhängig davon ob eine Bedingung zum filtern vorhanden ist, eine unsortierte Liste, deren Startkosten entsprechend niedrig sind. Je weiter die Liste durchlaufen wird, desto höher steigen die notwendigen Kosten. Die kostengünstigere Alternative ist der \texttt{Index Scan}, bei dem der Index nach den Kriterien durchsucht wird, was meist durch den Aufbau des Index als BTree (Multi"=Way Balanced Tree) rapide geht. Eine weitere Optimierungsmöglichkeit ist die Verwendung von Indexen. Diese sind aber mit Bedacht zu wählen, da bei mehreren Indexen, die sehr ähnlich sind, nicht immer der gewünschte Index bei der Abfrage verwendet wird. Auch bedeutet ein Index bei jeder Änderung der Daten zusätzliche Arbeit, da dieser entsprechend mit gepflegt werden muss und ebenso dessen Statistik muss regelmässig aktualisiert werden. Ebenfalls ist die Reihenfolge der Spalte in einem zusammengesetzten Index von Bedeutung. Als Grundlage sollte hier mit der Spalte gestartet werden, welche die größte Einschränkung durchführt. Zusätzlich muss die Art des Index definiert werden, welche davon abhängig ist, mit welcher Vergleichsoperation auf die Tabellenspalte zugegriffen wird. Um größere und aufwendigere Abfragen zu optimieren, bietet der PostgreSQL noch die Möglichkeit von \textit{Materialized View}. Diese sind sehr ähnlich zu den Sichten, zusätzlich werden aber die Ergebnisse in einer tabellenähnlichen Form abgespeichert, somit sind die Zugriff auf diese Daten häufig performanter als die eigentliche Abfrage. Daher muss abgewägt werden, ob die Performance-Verbesserung trotz der zusätzlichen Aktualisierung des Datenbestandes als sinnvoll erachtet werden kann. Zusätzlich kann über die Systemtabelle \texttt{pg\_statistic} oder die lesbarere Systemsicht \texttt{pg\_stats} die aktuelle statistischen Informationen über eine Tabelle und deren Spalten ermittelt werden. In dieser Tabelle werden durch das \texttt{ANALYZE} beziehungsweise \texttt{VACUUM ANALYZE} Kommando die Informationen zum Anteil der \texttt{NULL}"=Werte (null\_frac), durchschnittlichen Größe (avg\_width), unterschiedlicher Werte (n\_distinct) und 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 \linebreak\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.