Performance-Optimierung
Einleitung
Beim Erstellen kleiner und mittlerer QlikView-Dokumente müssen Sie sich über die Performance Ihrer Applikationen normalerweise keine Gedanken machen. Bei größeren Datenmengen hängt die Performance aber stark davon ab, wie die Applikation aufgebaut ist. Gegebenenfalls können Sie durch geringfügige Änderungen Berechnungszeiten und Speicherbedarf verringern und die Performance erheblich verbessern. In diesem Anhang werden einige häufig auftretende Performance-Fallen erläutert und Lösungen aufgezeigt.
Generell kann man sagen, dass sich die Performance verbessert, wenn Operationen im Skript statt in den Objekten des Dokuments vorgenommen werden. Aber häufig muss ein Kompromiss gesucht werden: Die Antwortzeit wird zwar verbessert, doch die verfügbare Funktionalität wird verringert. Daher sind die nachfolgenden Tipps sollten nicht allgemein als vorteilhaft erachtet werden. Testen Sie einfach, inwieweit sich die Performance Ihrer Applikation verbessert, und nutzen Sie die Hinweise, wenn sie Ihnen sinnvoll und wesentlich erscheinen.
Die folgende Liste enthält Beispiele für Methoden zum Beseitigen der oben beschriebenen Probleme. Das betreffende Problem wird beschrieben und es wird auf eine hilfreiche QlikView-Funktion hingewiesen. Werden mehrere Lösungen angeboten, lässt sich zwar nicht generell sagen, welche Methode die beste ist, die Reihenfolge kann jedoch als Hinweis betrachtet werden.
If( Bedingung(Text ), …)
If-Abfragen, die den Vergleich von Textwerten erfordern, sind im allgemeinen speicherintensiv. Eine Lösung für dieses Problem wäre, die Textwerte numerischen Werten zuzuordnen, z. B. mit Hilfe der autonumber-Funktion (siehe vorangehendes Beispiel), und/oder den Test im Skript durchzuführen.
Die Prüfung von Textwerten dauert länger als die Prüfung numerischer Werte. Bitte schauen Sie sich folgende Formel an:
If (Alfa= ‘ABC’, ‘ABC’, left (Alfa, 2))
Diese Abfrage kann ohne Einschränkung der Flexibilität im Skript gemacht werden:
Laden
*,
If (Alfa = ‘ABC’, 1, 0) as Flag
resident table_1 ;
Somit lässt sich folgende Formel verwenden:
If ( Flag = 1,’ABC’, left (Alfa, 2))
Die Prüfung wird auf diese Weise erheblich vereinfacht.
Sum( If( Bedingung, 'Feldname'… ))
Diese Aggregierung ist unabhängig von den Dimensionen der Tabelle, und das Ergebnis wird auf die Dimensionen verteilt. Für dieses Problem gibt es zwei mögliche Lösungen. Entweder wird die Prüfung im Skript vorgenommen, und die Aggregierung in der Tabelle oder die gesamte Operation wird im Skript durchgeführt. Dazu stehen verschiedene Methoden zur Verfügung, z. B. intervallabgleich, group by, peek oder if….then…else.
Es sind in diesem Fall zwei Schritte erforderlich: die Prüfung der Bedingung und die Aggregierung der Ergebnisse. Analog zum vorangehenden Beispiel ergibt sich mit der Aggregierung:
Sum ( If (Alfa= ‘ABC’, Num*1.25 , Num) )
Laden
*,
If (Alfa = ‘ABC’, 1, 0) as Flag
resident table_1 ;
Somit lässt sich folgende Formel verwenden:
Sum ( If ( Flag = 1, Num* 1.25 , Num ) )
Um die Aggregierung direkt im Skript vorzunehmen, benutzen Sie folgende Syntax:
Tabelle2:
Laden
*,
If (Alfa = ‘ABC’, 1, 0) as Flag
resident Tabelle1;
table_3:
Laden
Alfa,
If ( Flag = 1, Num* 1.25 , Num ) as NewNum
resident table_2 ;
table_4:
Laden
Alfa,
Sum( NewNum ) as SumNum
resident table_3
group by Alfa ;
If( Bedingung, Sum( 'FieldName' ) …)
Diese Konstruktion ist hier als Gegensatz zu dem vorangehenden Beispiel genannt. Diese Aggregierung ist kontextabhängig und verursacht im allgemeinen keine Performance-Probleme.
If( Bedingung1, Sum( 'FieldName' ), If(Bedingung2, Sum( 'FieldName' ) …
Die Logik verschachtelter If...then else...-Abfragen ist zwar in der Theorie nicht kompliziert, kann aber in der Praxis schwierig zu handhaben sein. Es sind schon Fälle mit Hunderten von Verschachtelungen vorgekommen. Dies ist speicherintensiv und beansprucht die CPU extrem. Oftmals können die „Bedingungen“ durch Umgestaltung ersetzt werden. Ein typisches Beispiel ist die Aggregierung von Menge * Preis, wobei der Preis variabel ist. Hier kann der erweiterte intervalmatch-Befehl verwendet werden. Sollen etwa zwei Bedingungen A und B erfüllt sein, so kann diese Prüfung auch mit Hilfe einer neuen Bedingung C erfolgen.
Beispiel:
sum((GAC12_STD_COST * GAC15_EXCHANGE_RATE) * GIV24_DISP_QTY)
Ersetzt
Sum(
If((GAC12_EFCT_DT<= GIV23_REJ_DT and
GAC12_EXPIRE_DT>GIV23_REJ_DT) and
(GAC15_EFCT_DT<= GIV23_REJ_DT and GAC15_EXPIRE_DT>GIV23_REJ_DT),
GAC12_STD_COST * GAC15_EXCHANGE_RATE) * GIV24_DISP_QTY,
Null()))
und
Sum(
If(GAC12_EFCT_DT<= GIV23_REJ_DT,
If(GAC12_EXPIRE_DT>GIV23_REJ_DT,
If(GAC15_EFCT_DT<= GIV23_REJ_DT,
If(GAC15_EXPIRE_DT>GIV23_REJ_DT,
(GAC12_STD_COST * GAC15_EXCHANGE_RATE) * GIV24_DISP_QTY,
Null())))))
indem die Felder GAC12_STD_COST und GAC15_EXCHANGE_RATE als Slowly Changing Dimensions eingelesen werden.
Alphabetische Sortierung
QlikView prüft beim Einlesen automatisch, ob ein Feld numerische Werte oder Strings oder allgemeine Werte enthält. Felder die als Text bewertet werden, sortiert QlikView als Text. Dies ist die Sortierung, die die längste Bearbeitungszeit erfordert. Wenn Sie stattdessen die Sortierung nach Lade-Reihenfolge wählen, lässt sich ein Performance-Gewinn erzielen. Überlegen Sie daher, welche Sortierfolge Sie in den Objekten benötigen, und verzichten Sie gegebenenfalls auf die alphabetische Sortierung.
QlikView sortiert Strings, in denen Zeichen und Zahlen enthalten sind, in alphanumerischer Reihenfolge. Das heißt, dass Zahlen nach Ihrem Wert sortiert werden und Zeichen, die keine Zahlen sind, in ASCII-Reihenfolge sortiert werden, im Gegensatz zur üblichen Sortierfolge nur nach ASCII. Beispiel:
ASCII-Sortierung | Alphanumerische Sortierung |
---|---|
A1 | A1 |
A10 | A4 |
A11 | A5 |
A30 | A6 |
A4 | A10 |
A5 | A11 |
A6 | A30 |
Dynamische Ausdrücke
Dynamische Ausdrücke lassen sich in QlikView fast überall verwenden, wo Text einzugeben ist. Der Ressourcenbedarf einer Formel hängt aber immer davon ab, wo die Formel benutzt wird. Formeln in Diagrammen werden im Dialog „Formel bearbeiten“ editiert und nur dann neu berechnet, wenn das Objekt sichtbar ist und die Daten sich ändern. Formeln minimierter Diagramme werden beispielsweise bei Auswahlaktionen nicht neu berechnet.
Wird aber beispielsweise ein dynamischer Ausdruck für die Titelleiste eines Objekts definiert, so wird dieser Ausdruck bei jeder Änderung neu berechnet. Es gibt zudem viele verschiedene Möglichkeiten zum Definieren von Anzeigebedingungen, Berechnungsbedingungen usw. Diese Tests werden ebenfalls immer durchgeführt.
Manche Formeln sind speicherintensiver als andere. Je öfter eine Formel neu berechnet werden muss, umso mehr Speicher wird benötigt. Seit in QlikView die asynchrone Aktualisierung von Objekten eingeführt wurde, fällt Ihnen dieser Effekt möglicherweise mehr auf als vorher.
Die Funktionen für Datum und Uhrzeit, z. B. now und today, verwenden Daten der Systemuhr für die Berechnung und werden immer aktualisiert, wenn sich diese ändern. Insbesondere die Funktion now kann zu Performance-Problemen führen, weil sie jede Sekunde neu berechnet wird.
Hier ein Beispiel:
If ( ReloadTime()+3>Now(), 'Old Data', 'New Data')
In diesem Fall können Sie unter Umständen auch folgende Formel verwenden:
If ( ReloadTime()+3>Today(), 'Old Data', 'New Data')
Sie können den Sachverhalt leicht testen, indem Sie zwei Textboxen anlegen, in denen jeweils eine der Formeln steht. Verschieben Sie nun beide Textboxen mit Now() zusammen und vergleichen Sie die Berechnungszeiten.
Makro-Auslöser
Mit Hilfe der Makro-Auslöser können bei annähernd allen Ereignissen innerhalb der Applikation Makros gestartet werden. Seien Sie an dieser Stelle vorsichtig mit rekursiven Ereignissen, bei denen ein Ereignis das nächste auslöst, welches wiederum das nächste auslöst usw.