Performance-Optimierung von Notes-Anwendungen (Teil 2)

von Christoph Gerken,
assono GmbH, Standort Kiel,

Vor einiger Zeit haben wir uns bereits Gedanken gemacht, warum eine Notes-Anwedung langsam sein kann, welche Lösungsansätze es generell gibt und wie man als Entwickler auf Masken- und Ansichtsebene korrigierend eingreifen kann. Nun soll ein genauerer Blick auf weitere Bestandteile von Notes-Datenbanken, insbesondere auf den Programmcode, folgen. Masken und Ansichten können noch so performant sein, wenn der Benutzer bei allen anwendungsspezischen Aktionen, die er ausführt, trotzdem warten muss.

Agenten

Aufwändige Prozesse, die nicht direkt während einer Nutzeraktion ausgeführt werden müssen, lassen sich an zeitgesteuerte Agenten auslagern. Dazu muss möglicherweise nur ein entsprechendes Flag gesetzt werden und alles weitere passiert dann im Hintergrund, ohne dass der Nutzer unnötig warten muss.

Arbeitet der Nutzer auf einer Server-Datenbank und ist seine Anbindung nicht optimal, können aufwändige Berechnungen sehr lange dauern. Ist (im Gegensatz zum vorigen Absatz) eine sofortige Berechnung nötig, kann man diese in einen Agenten auslagern und diesen per RunOnServer ausführen. Erst, wenn der Agent fertig ist, überträgt er die Ergebnisse an den Client, sodass nur wirklich relevante Datenströme fließen.

Innerhalb von zeitgesteuerten Agenten kommt es häufig nicht auf die allerbeste Optimierung an, da diese im Hintergrund meistens genügend Zeit haben, ihren Dienst zu verrichten. Bei aufwändigen Operationen wie dem Vergleich großer Datenmengen kann man dem Agenten die Arbeit jedoch per Hashes (= nahezu eindeutige Schlüsselwerte) deutlich vereinfachen. Dazu bildet man beispielsweise über ganze Textabsätze oder die Kombination vieler Feldwerte einen Hashwert (z. B. beim Speichern eines Dokumentes per @Password). Dann muss der Agent nur noch einen einzigen, kurzen String vergleichen, um zu entscheiden, ob weitere Operationen nötig sind.

Bei der Bearbeitung großer Dokumentmengen ist zudem darauf zu achten, dass nur notwendige Operationen durchgeführt werden. Besonders kostspielige Operationen sind:

  • Speichern von Dokumenten: Statt in jedem Agentendurchlauf jedes Dokument zu speichern, sollte man dies nur tun, wenn sich tatsächlich relevante Feldwerte geändert haben
  • ComputeWithForm: Je mehr Felder sich ändern, desto mehr hat der Domino-Server zu tun. Wenn also nur einige wenige Felder wirklich ein Update benötigen, sollten diese punktuell durch den Programmcode vorgenommen werden.
  • Löschen von Dokumenten: Unnötige Deletions Stubs sind, wie in Teil 1 beschrieben, zu vermeiden. Insbesondere sollte man deshalb bei Agenten darauf achten, bestehende Dokumente zu aktualisieren, statt sie "der Einfachheit halber" zu löschen und neu anzulegen.
  • Verschachtelte Schleifen: Ihre Verarbeitungzeit wächst mit der Menge der zu verarbeitenden Informationen. Oft gibt es bessere Algorithmen oder kreative Wege, solche Konstrukte zu vermeiden.

LotusScript


Einige der obigen Anmerkungen zu Agenten gelten natürlich auch allgemein für LotusScript.

Bei der Suche nach Dokumenten ist die FTSearch der einfachen Search und der Suche per NotesNoteCollection vorzuziehen. Natürlich sollte die Datenbank in dem Fall volltextindiziert sein.

Der Zugriff auf bestimmte/bekannte Dokumente wird am schnellsten per GetDocumentByUNID ausgeführt. Gerade wenn man nacheinander auf viele Dokumente zugreifen möchte, kann es sich lohnen, zunächst die UNIDs aus einer Ansicht/DocumentCollection in eine Liste einzulesen und dann statt einzelner Lookups einfach die UNID aus der Liste zu holen. Wenn man hingegen nur wenige Lookups durchführen möchte, tun es auch die relativ schnellen GetAllDocumentsByKey- und GetDocumentByKey-Methoden.

Benötigt man nur Zugriff auf einzelne Werte aus der Ansicht statt auf das ganze Dokument, ist es noch besser, GetAllEntriesByKey bzw. GetEntryByKey zu verwenden und dann bei Bedarf die ColumnValues auszulesen.

Generell sollte man vor dem Durchlaufen ganzer Ansichten die Eigenschaft AutoUpdate auf False setzen, da sonst jedes Mal, wenn ein neues Dokument angesprochen wird, die Ansicht aktualisiert wird. Besonders effizient durchläuft man große Dokument(-teil-)mengen in Ansichten mittels NotesViewNavigator:

Call view.Refresh()
view.AutoUpdate = False

Set vwn = view.CreateViewNavFromCategory("MyCategory") REM specify your navigator, e. g. by category
vwn.BufferMaxEntries = 400
vwn.EntryOptions = VN_ENTRYOPT_NOCOUNTDATA

Set vwe = vwn.GetFirst()
Do Until vwe Is Nothing
	REM do here what you must do
	Set vwe = vwn.GetNext(vwe)
Loop

view.AutoUpdate = True

Einige kleinere LotusScript-Tipps für alle Lebenslagen

Die Rangfolge der Schleifengeschwindigkeiten lautet ForAll > For Next > Do Until/Do While

Immer Option Declare verwenden und keine Mehrfach-Statements nutzen. Bei Dim i, j As Integer ist i ein Variant!

If-Abfragen in LotusScript hintereinander ausführen: If a Then If b Then ist schneller als If a And b Then. Anders als bei anderen Programmiersprachen wird b immer ausgewertet, auch wenn a False ist.

doc.GetItemValue("x") ist schneller (und meines Erachtens besser lesbar) als doc.x. Das gleiche gilt für ReplaceItemValue.

Array mit fester Größe lassen sich etwas schneller verarbeiten als dynamische Arrays.

Datenbankeigenschaften

Spätestens zum Abschluss der (Um-)Programmierung einer Datenbank sollte man die Datenbankeigenschaften beachten. Einige der Optionen sind definitiv bei jeder Anwendung einen Blick wert.

Mögliche Einstellungen unter Eigenschaften\Datenbank\Erweitert
  • Keine Ungelesen-Markierungen verwalten: Aktivieren, sofern den Anwendern nicht angezeigt werden muss, ob sie Dokumente bereits gelesen haben.
  • Dokumententabelle in Ansicht optimieren: Aktivieren, falls sich der Form-Wert von Masken in der Datenbank nicht ändert.
  • Freien Platz nicht überschreiben: Aktivieren
  • LastAccessed-Eigenschaft verwalten: Deaktivieren, sofern nicht verwaltet werden muss, wann ein Dokument zuletzt geöffnet wurde.
  • Spezielle Antworthierarchie nicht unterstützen: Aktivieren, falls @AllChildren und @AllDescendants nicht verwendet wird.
  • LZ1-Komprimierung für Anhänge verwenden: Aktivieren
  • Mehr Felder in der Datenbank zulassen: Aktivieren
  • Einträge in $UpdatedBy-Feldern begrenzen/Einträge in $Revisions-Feldern begrenzen: Auf geringe Werte oder 0 setzen, wenn Änderungen an Dokumenten nicht/in geringem Umfang dokumentiert werden sollen oder bereits anderweitig dokumentiert werden.

Zusammenfassung

Damit haben wir die wichtigsten Punkte zu diesem Thema besprochen. Natürlich gibt es noch eine Menge weiterer anwendbarer Kniffe. Nach Umsetzung all dieser Ideen wird Ihre Anwendung jedoch schon spürbar flotter laufen.

Wir unterstützen Sie natürlich gerne, Ihre Anwendungen auf höchste Performance zu optimieren. Sprechen Sie uns hierzu einfach unter +49 4307 900 408 oder per Mail an kontakt@assono.de an.

Nächste Artikel in dieser Reihe:

Das könnte Sie auch interessieren:

Entwicklung IBM Notes und Domino

Quelle: Datenbankeigenschaft "Optimize document table map"

Fachbeitrag IBM Notes IBM Domino Entwicklung

Sie haben Fragen zu diesem Artikel? Kontaktieren Sie uns gerne: blog@assono.de

Sie wollen eine individuelle Lösung? Kontaktieren Sie uns

Weitere interessante Artikel

Sie haben Fragen oder möchten eine Demo anfordern?

Wenn Sie mehr über unsere Angebote erfahren möchten, können Sie uns jederzeit kontaktieren. Gerne erstellen wir eine individuelle Demo für Sie.

Wir verwenden Ihre Daten, um Sie einmalig per E-Mail zu kontaktieren. Wir geben Ihre Daten nicht an Dritte weiter. Siehe: Datenschutzhinweise
assono GmbH

Standort Kiel (Zentrale)
assono GmbH
Lise-Meitner-Straße 1–7
24223 Schwentinental

Standort Hamburg
assono GmbH
Bornkampsweg 58
22761 Hamburg

Telefonnummern:
Zentrale: +49 4307 900 407
Techn. Hotline: +49 4307 900 403
Vertrieb: +49 4307 900 402

E-Mail-Adressen:
kontakt@assono.de
bewerbung@assono.de