Vermeidung von Performance-Einbruch durch Dashboards
Ausgangssituation
Manchmal kann beobachtet werden, dass die Performance von größeren Datenbanklösungen sich ungefähr proportional zur Anzahl gleichzeitig darin arbeitender Nutzer verschlechtert. Diese Datenbanken verwenden oft Dashboards in welchen sich Ansichtselemente und Formelfelder befinden die Datensätze aus großen Tabelle selektieren und anzeigen bzw. verarbeiten, z.. B. Aufgaben, Aufträge, Leads, etc.
Die Ursache
Formelfelder und Ansichtselemente aktualisieren dynamisch ihre Inhalte entsprechend des "Long Polling", das bedeutet, dass alle 30 Sekunden diese Felder prüfen ob ihre Daten noch aktuell sind.
Dieser Rhythmus wird jedoch durchbrochen sobald durch die Synchronisationsprozesse ein Nutzergerät davon erfährt, dass ein anderer Nutzer eine Änderung an einem für die Formelausführung relevanten Datenstamm verändert hat. Primär von diesem Verhalten betroffen sind Ausführungen von "select", da in jedem Moment das System wissen muss ob die dem Nutzer angezeigten Datensätze auch die sind die er anhand der entsprechenden Konditionen sehen soll.
Das führt nun zu folgendem Verhalten:
Nutzer 1 und 2 arbeiten zeitgleich und schauen sich beide das Dashboard mit der Ansicht an in welcher Aufgaben zu sehen sind. Die Aufgabentabelle hat möglicherweise mehrere tausende Datensätze, aber den Nutzern werden jeweils nur ihre aktuell relevanten Datensätze angezeigt (z. B. je ein Dutzend).
Wenn keiner von beiden Datenfeldinhalte bearbeitet aktualisieren sich die Ansichten automatisch alle 30 Sekunden indem vom Server die aktuelle Datenlage abgefragt wird.
Nutzer 1 öffnet nun einen seiner Aufgaben-Datensätze als Popup über dem Dashboard und verändert irgendeinen Datenwert, z. B. den Status der Aufgabe.
Das Gerät von Nutzer 1 schickt die Info über die Änderung an den Server.
Der Server streut diese Änderung an die aktuelle Nutzerschaft der Datenbank, in diesem Fall Nutzer 2.
Das Gerät von Nutzer 2 bemerkt die Änderung und - außerhalb des "Long Polling"-Rhythmus - ruft die zu selektierenden Daten neu vom Server ab da es ja sein könnte, dass sich hierdurch die für Nutzer 2 anzuzeigenden Daten ändern werden.
Der Superlativ
Man stelle sich nun aber vor, dass statt zwei Nutzern zehn/zwanzig/dreißig gleichzeitig arbeiten. Jedes Mal wenn irgendein Nutzer eine Änderung durchführt, würden dadurch dann die Geräte aller anderen neun/neunzehn/neunundzwanzig Nutzer die Daten neu beim Server abfragen, was den Server verlangsamt und somit auch die Arbeitsgeschwindigkeit aller Nutzer.
Die Lösung: "Delayed Select"
Im Anhang dieses Artikels befindet sich eine Datenbank in der das Prinzip des "Delayed select" praktisch demonstriert wird. Hierbei befinden sich nicht in den Ansichten und Formelfeldern die "select"-Anweisungen, stattdessen wird "select" per Registerkarten-Trigger einmal beim Anzeigen des Dashboard (oder bei Bedarf über den Aktualisieren-Knopf "Refresh" ) ausgeführt und das Ergebnis in einem Client-seitigen Textfeld zwischengespeichert. Der Inhalt dieses Textfeldes wird dann von Formelfeldern und Ansichten wieder entschlüsselt um per Funktion record() in einer for-Schleife die Datensätze zu sammeln die angezeigt werden sollen.
Oberflächlich macht das quasi keinen Unterschied (bis auf den Bedarf zur Aktualisierung der Ergebnisse das Dashboard neu zu öffnen oder den Knopf zu betätigen), aber im Hintergrund wird hierdurch sowohl Long Polling als auch die erzwungene Aktualisierung bei jeder Datenstandänderung vermieden. Die Anwendung dieses Prinzips hat bereits nachweislich in vielen Fällen einen signifikanten Unterschied in der Nutzbarkeit gemacht und auch bei großer gleichzeitiger Nutzerzahl eine stabile Performance gewährleistet.
