## Nutzungsdaten

Der Forscher wird im Laufe seiner Arbeit die Anwendung mit Daten füllen. Dabei wachsen die Datenbank
und die Menge der zu verwaltenden Dateien. Ziel ist es, dass die Anwendung auch nach einer
langfristigen Arbeit noch gefühlt genauso schnell arbeitet wie zum Anfang auch.

Um die Last der Nutzungsdaten zu testen, wurde eine einheitliche Testumgebung und Grenzwerte für die
Zeiten definiert. Als Testumgebung wurde ein 10 Jahre alter Laptop mit 4 Kernen, 8 GB RAM und 256 GB
SSD festgelegt. Für alle Tests wurde immer wieder die gleiche Umgebung gewählt. Die Datenbank wurde
mit Daten gefüllt und dann wurden verschiedene Suchanfragen gestellt oder durch die Daten navigiert.
Der Vorteil an dieser beschränkten Umgebung ist, dass die verwendeten Laptops der Forscher alle
neuer und leistungsstärker sind, wodurch auszugehen ist, dass diese es leichter haben werden, mit der
Menge an Daten umzugehen.

Für die Grenzwerte bei den Zeiten wurde definiert, dass eine einfache Navigation nie länger als 1
Sekunde dauern darf. Bei einer Suchanfrage müssen schon nach maximal 3 Sekunden erste Ergebnisse zu
sehen sein. Nach 10 Sekunden ist die Suche beendet. Ist der gewählte Suchausdruck komplexer, dann
sind 60 Sekunden erlaubt. Das Öffnen der aggregierten Ansicht von Einträgen muss nach 3 Sekunden
fertig sein. Die Oberfläche muss flüssig auf Nutzereingaben reagieren. Diese Schwellwerte wurden
dahingehend festgelegt, dass diese zum einen für einen Nutzer vertretbar sind und zum anderen ein
ungestörtes Arbeiten ermöglichen.

Nachdem die Umgebung und die Grenzwerte definiert sind, geht es darum festzustellen, wie viele Daten
ein Forscher überhaupt anlegen wird. Dazu wurden die Forscher aus der Testgruppe befragt, was sie
sich vorstellen könnten und es wurden alte Projekte angesehen, um eine gute Abschätzung zu erhalten.


\begin{mytable}{Größe der Testdatenbank}{nutzungsdaten-groesse} \centering
\begin{tabulary}{1.0\textwidth}{|L|L|L|L|} \hline Kategorie & Erzeugte Datenbank & Erwartete
Realwerte & Kommentar \\
    \hline
    \hline
    Anzahl von Interviews & 1000 & ca. 10-15 & \\
    \hline
    Anzahl von Personen & 5000 & ca. 50 & \\
    \hline
    Anzahl an genutzten Rollen & 2 & ca. 5-10 & dies hat keine Auswirkung auf die Suchperformance \\
    \hline
    Anzahl an Attributen pro Rolle & 7 und 182 & ca. 10-15 & jeweils zu ca. 50\% genutzt \\
    \hline
    Anzahl an Attributen & ca. 472.000 & ca. 625 & \\
    \hline
    Länge der Texte & ca. 2,5 KB & ca. 50 KB & Für die Suche wurden kürzere Texte mit mehr Attributen gewählt \\
    \hline
    Anzahl der Einträge in der Historie & ca. 5 & ca. 50 & Historie wird für die Suche ignoriert \\
    \hline
    Speicher & ca. 2,3 GB & ca. 650 MB & \\
    \hline

\end{tabulary} \end{mytable}

Für die Testfälle wurden dann diese Zahlen großzügig multipliziert (siehe Tabelle
\ref{nutzungsdaten-groesse}), um eine deutlich größere Datenbank zu erhalten. Für die
Textgenerierung wurden Markov-Ketten von diversen Wikipedia-Artikeln genutzt. Dadurch werden einer
natürlichen Sprache ähnliche Texte erzeugt, die beliebig lang sein können, aber keine Bedeutung
haben. Die Texte wurden mit Absicht kürzer gewählt als in den erwarteten Werten, da die
Textgenerierung über Markov-Ketten recht lange braucht (in der aktuellen Konfiguration schon 5-10
Minuten für die komplette Datenbank). Die resultierende Datenbank ist trotzdem groß genug.

Dabei stellte sich heraus, dass der anfängliche naive Suchalgorithmus sehr langsam ist. Es werden 30
bis 120 Sekunden für Suchanfragen benötigt. Bei dem naiven Suchalgorithmus wurden alle Einträge aus
der Datenbank einzeln ausgelesen, mit dem Suchquery abgeglichen und dann weitergereicht. Sobald alle
Einträge überprüft wurden, wurde das an die Oberfläche weitergereicht. Auch das Abrufen der
aggregierten Seiten ist unverhältnismäßig lang mit 5-10 Sekunden.

Danach wurden mehrere Optimierungen an den Algorithmus vorgenommen, die aber aus zeitlichen Gründen
nicht einzeln auf ihre Effektivität überprüft wurden. Stattdessen wurde jede Optimierung beibehalten
und wirkte somit auch auf die weiteren Optimierungen aus.

Zuerst wurden die Verknüpfungen von Objekten nun auf beiden Seiten hinterlegt. Vorher wurde eine 1-n
Verknüpfung so abgebildet, dass beim n-Element nur die ID des 1-Elements hinterlegt wurde, anders
herum nicht. Das bedeutete also, wenn alle Verknüpfungen des 1-Elements abrufen werden sollen, musste
die komplette Datenbank durchsucht werden. Nun ist zusätzlich beim 1-Element eine Liste der IDs
hinterlegt. Das erhöht den Synchronisierungsaufwand, dafür sind Beziehungen schneller verfügbar.
Außerdem wurden verschiedene Elemente (Attribute, Attributshistorie, Einträge von Dateien) aus den
jeweiligen Elternelementen ausgegliedert und erhielten ihre jeweils eigenen Collections. Das erhöht
auch wieder den Verwaltungsaufwand, da mehr Objekte verwaltet werden müssen.

Diese Änderungen hatten zur Folge, dass sich an der Größe der Datenbank nicht wirklich etwas
geändert hat. Dafür sind die Abfragen für aggregierte Ansichten auf unter 200 ms gesunken. An der
Suchperformance hat dies nicht viel geändert.

Als Nächstes wurde ein Such-Index (nicht zu verwechseln mit dem Index, den LiteDB bereitstellt),
aufgebaut. Dazu werden alle aktuellen Texte (die aus der Historie werden derzeit ignoriert) in
Tokens aufgespalten und umgewandelt. Ein Token ist eine Folge von Kleinbuchstaben und Zahlen.
Großbuchstaben werden in Kleinbuchstaben umgewandelt. Akzente und Sonderzeichen werden entfernt. Der
Index enthält dann zu jedem Token den jeweiligen Fundort. Beim Fundort werden nur die ID und Art des
Eintrags berücksichtigt. Jeder Suchstring wird auch in die entsprechenden Tokens umgewandelt und
dann wird für jeden Suchtoken herausgesucht, welche Einträge infrage kommen. Die Mengen an
Einträgen für jedes Suchtoken werden dann mengentheoretisch zusammengefasst. Heraus kommt eine Liste
an in Frage kommenden Einträgen.

Da der Index unter Umständen auch vertrauenswürdige Daten enthält, wird für die Confidential und die
normale Datenbank jeweils ein eigener Index angelegt.

Jeder Token kann wieder eine Menge an kürzeren Tokens enthalten, indem vom Anfang und Ende eine
beliebige Menge an Zeichen entfernt wird. Dies ermöglicht die Suche nach Teilwörtern, ohne das ganze
Wort zu kennen. Experimentell hat sich herausgestellt, dass es unpraktisch ist, als minimale Länge
eines Tokens 1 zu nehmen. Hierbei ist der Index auf die 10-fache Größe der Datenbank angewachsen und
das noch bevor ein Zehntel der Datenbank gelesen wurde. Stattdessen wurde als minimale Länge 3
genommen, da dies ein guter Vergleich zwischen Größe des Index und der Datenbank ist (2,3 GB
Datenbank und 1,0 GB Index).

Der Einsatz eines Index hatte nun zur Folge, dass bei Suchanfragen, die Schlüsselwörter genutzt
haben, nun eine Antwort in Sekundenbruchteilen zu sehen ist. Falls allgemeinere Sachen benötigt
werden, so dauert eine Suche immer noch genauso lang.

Bis zu diesem Zeitpunkt wurden die Ergebnisse einer Suche auf dem Server zurückgehalten, um sie dann
zu sortieren und im Anschluss an die Oberfläche weiterzureichen. Diese wurde damit behoben, dass
sämtliche Ergebnisse, sobald sie verfügbar sind, nun direkt mit ein paar Hinweisen zur Sortierung an
die Oberfläche weitergereicht werden. Die Oberfläche sortiert dann selbstständig die Ergebnisse und
ordnet sie schon der Menge bekannter Ergebnisse ein. Dies hat zur Folge, dass erste Ergebnisse
schnell zu sehen sind, die aber mit der Zeit weiter verbessert werden können.

Nach diesen Umstrukturierungen und Anpassungen haben sich Suche und die Anzeige aggregierter
Ansichten stark verbessert. Zum Schluss hin konnten alle zeitlichen Grenzen auf der Testumgebung
erreicht werden. Es gibt Ideen, die Suche noch weiter zu verbessern, welche all in zukünftigen
Erweiterungen (siehe \ref{082-suchoptimierungen}) kommen können.
