diff --git a/chapters/thesis/chapter05.tex b/chapters/thesis/chapter05.tex index 56474e7..b1d8b01 100644 --- a/chapters/thesis/chapter05.tex +++ b/chapters/thesis/chapter05.tex @@ -260,16 +260,18 @@ 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} und \textit{openjpa.""DataCache} auf -\textit{ehcache} anzupassen. Die Objekte oder mindestens das Hauptobjekt benötigt noch die Annotation -\textbf{@DataCache(name = "userCache")}, damit der Cache für die Klassen aktiviert wird. Als letztes muss noch der +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 +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 Cache"=Manager aktiviert werden, dieser kann entweder durch Code programmiert werden oder über eine Konfiguration in der \textit{ehcache.xml}. -Anhand der Auswertung von \ref{tbl:measure-ehcache-active} fällt auf, dass der Cache keine Geschwindigkeitsvorteile -bringt. Zusätzlich werden trotz aktiven Cache die Anzahl der Anfragen an die Datenbank nicht reduziert. Gleichzeitig -sieht man aber anhand der Statistik"=Ausgaben, dass der Ehcache verwendet wird und entsprechende Hits hat und der -OpenJPA"=Cache nicht mehr verwendet wird. Zusätzlich steigt der Speicherverbrauch stärker als in anderen Fällen. +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 +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. % document, documentaddresseeperson, first/last, documentcoauthorperson, count und documentfacsimile \begin{table}[h!] @@ -279,14 +281,14 @@ OpenJPA"=Cache nicht mehr verwendet wird. Zusätzlich steigt der Speicherverbrau \hline & \multicolumn{3}{c|}{Aufrufzeit (ms)} & \multicolumn{2}{c|}{Queries (ms)} & \multicolumn{3}{c|}{Memory (MB)} & \multicolumn{3}{c|}{Render (ms)} & \multicolumn{3}{c|}{DB-load (ms)} \\ \hline - \# & min & avg & max & \#"=avg & avg & start & stop & diff & min & avg & max & min & avg & max \\ + \# & min & avg & max & \#"=avg & avg & start & stop & diff & min & avg & max & min & avg & max \\ \hline %- & 151 & 368 & 1904 & 141.2 & 20.8 & 906.3 & 936.8 & 30.5 & 164 & 404 & 2232 & 39 & 124 & 847 \\ % 1412 - 208 ms (133+ 40+ 23+9+2+1) (#2,4-6,10,12) - 1 & 450 & 934 & 3026 & 1095.2 & xxxx & 977.1 & 1027.0 & 49.9 & 592 & 978 & 3015 & 464 & 656 & 1348 \\ % 10952 - ... ms ( .+ .+ .+.+.+.) (#.) - 2 & 503 & 563 & 666 & 1206.0 & xxxx & 1028.0 & 1126.0 & 98.0 & 494 & 554 & 555 & 395 & 448 & 453 \\ % 23012 - - 3 & 431 & 522 & 586 & 1206.0 & xxxx & 1137.0 & 1370.0 & 233.0 & 422 & 513 & 575 & 341 & 430 & 494 \\ % 35072 - - 4 & 421 & 497 & 635 & 1206.0 & xxxx & 1371.0 & 1469.0 & 98.0 & 414 & 490 & 627 & 337 & 414 & 551 \\ % 47132 - - 5 & 444 & 511 & 600 & 1206.0 & xxxx & 1469.0 & 1662.0 & 193.0 & 436 & 503 & 589 & 362 & 420 & 505 \\ % 59192 - + 1 & 156 & 488 & 2820 & 135.2 & xxx & 981.6 & 1006.0 & 24.4 & 147 & 490 & 2809 & 39 & 175 & 1186 \\ % 1352 - + 2 & 135 & 144 & 166 & 6.0 & xxx & 1006.0 & 1007.0 & 1.0 & 124 & 136 & 157 & 33 & 38 & 47 \\ % 1412 - + 3 & 121 & 129 & 136 & 6.0 & xxx & 1008.0 & 1009.0 & 1.0 & 113 & 121 & 126 & 32 & 34 & 33 \\ % 1472 - + 4 & 116 & 123 & 133 & 6.0 & xxx & 1008.0 & 1016.0 & 8.0 & 108 & 116 & 125 & 31 & 33 & 34 \\ % 1532 - + 5 & 111 & 118 & 127 & 6.0 & xxx & 1016.0 & 1012.0 & -4.0 & 104 & 111 & 119 & 32 & 34 & 38 \\ % 1592 - \hline \end{tabular} } @@ -474,8 +476,76 @@ Geschwindigkeit optimiert. \section{Optimierung der Abfrage} \label{sec:performance-investigation-application:optimizing-query} -Für die Optimierung der Abfrage wird zuerst die Hauptabfrage ermittelt, die auch in \autoref{lst:documentlist} zu -sehen ist. +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 Mithilfe von pev2 +\citep{GitHubda51:online} visualisiert. + +\begin{lstlisting}[language=SQL,caption={Explain für Diagnose},label=lst:explain-diagnostic] +explain (analyze, verbose, buffers, summary, format json) +select +from + public.document t0 + left outer join public.historicalperson t1 on t0.authorperson_id = t1.id + left outer join public.sitecity t5 on t0.city_id = t5.id + left outer join public.appuser t6 on t0.editor_id = t6.id + left outer join public.extendedbiography t2 on t1.extendedbiography_id = t2.id + left outer join public.sitecity t3 on t1.sitecity_birth_id = t3.id + left outer join public.sitecity t4 on t1.sitecity_death_id = t4.id + left outer join public.appuserrole t7 on t6.appuserrole_id = t7.id +where (t0.validuntil > NOW() + and t0.ispublishedindb = true) +order by startyear DESC, startmonth DESC, startday DESC +limit 400; +\end{lstlisting} + +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. + +\begin{figure}[h!] + \includegraphics[width=\linewidth]{gfx/chapter05_ExplainVisualize.png} + \caption{Visualisierung EXPLAIN} + \label{fig:explain-visualize} +\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 +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 kostengeringer 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 +\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 +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. + +\begin{lstlisting}[language=SQL,caption={Optimierung mit Common Table Expression},label=lst:explain-optimize-cte] +with doc_limit as ( + select id + from public.document + where validuntil > now() + and ispublishedindb = true + order by startyear desc, startmonth desc, startday desc + limit 400 +) +select * +from doc_limit t + join public.document t0 on t0.id = t.id +order by t0.startyear desc, t0.startmonth desc, t0.startday desc +\end{lstlisting} + +\begin{lstlisting}[language=SQL,caption={Index für Common Table Expression},label=lst:explain-optimize-cte-idx] +create index idx_document_with_stmt on document using btree + ( ispublishedindb, validuntil, startyear desc, startmonth desc + , startday desc, id ); +\end{lstlisting} \section{Materialized Views} \label{sec:performance-investigation-application:materialized-views} diff --git a/expose-ref.bib b/expose-ref.bib index bf8f29d..9177e79 100644 --- a/expose-ref.bib +++ b/expose-ref.bib @@ -81,6 +81,15 @@ urldate = {2024-09-14} }, +@online{GitHubda51:online, + author = {}, + title = {GitHub - dalibo/pev2: Postgres Explain Visualizer 2}, + url = {https://github.com/dalibo/pev2}, + month = {}, + year = {}, + urldate = {2024-09-20} +}, + @online{AspNetCore:2024:MVC, year = 2024, url = {https://learn.microsoft.com/de-de/aspnet/core/fundamentals/middleware/?view=aspnetcore-8.0}, diff --git a/gfx/chapter05_ExplainVisualize.png b/gfx/chapter05_ExplainVisualize.png new file mode 100644 index 0000000..b6e4000 Binary files /dev/null and b/gfx/chapter05_ExplainVisualize.png differ diff --git a/gfx/chapter05_ExplainVisualize_with.png b/gfx/chapter05_ExplainVisualize_with.png new file mode 100644 index 0000000..76fe331 Binary files /dev/null and b/gfx/chapter05_ExplainVisualize_with.png differ diff --git a/thesis.pdf b/thesis.pdf index 07dc529..f986903 100644 Binary files a/thesis.pdf and b/thesis.pdf differ