Kategorie-Archiv: Performance

Preceding loads, Datentypen und distinkte Werte

Einführung

Im letzten Beitrag habe ich den durch ein Preceding Load verursachten Overhead betrachtet. In diesem Beitrag gehe ich genauer darauf ein, ob der Datentyp (oder was in QlikView als Datentyp durchgeht) oder die Anzahl der unterschiedlichen Werte einen größeren Einfluss auf die Performance haben. Das Ergebnis hat mich überrascht…

Anzahl der distinkten Werte

Wir vergleichen die Geschwindigkeit beim Kopieren einer Tabelle (mit Preceding Load Schicht) in eine andere mit Feldern mit unterschiedlicher Anzahl distinkter Werte. Jeweils 1 Spalte und 1000 Zeilen werden kopiert, diese enthalten entweder 100, 200, 300, 500, 800 oder 1000 unterschiedliche Werte. Welches Ergebnis habe ich erwartet? Entsprechend dem Beitrag im QlikView Design Blog über Symbol tables and Bit-stuffed pointers erwarte ich einen geringeren Schreibaufwand für weniger distinkte Werte, da der Pointer in der Symboltabelle entsprechend kleiner ist (100 Werte = 7 Bit, 1000 Werte = 10 Bit).

Hier ist das Ergebnis:

PL with Float, 1c, 1000r, 100dv to 1000dv

Zu meiner Überraschung habe ich nahezu keinen Unterschied zwischen den verschiedenen Varianten feststellen können.

Unterschiedliche Datentypen

Schauen wir uns das Ergebnis des Vergleichs unterschiedlicher Datentypen an. Hier kopieren wir (mit Preceding Load Schicht) jeweils 1 Spalte und 1000 Zeilen mit 100 distinkten Werten, die allerdings unterschiedlichen Datentypen entsprechen.

Integer: 2, 4, 6, etc. (keine geschlossene Reihe, um die sequentielle Integer Optimierung zu vermeiden)

Float: 0.9, 1.9, 2.9, etc.

Text: 1Text, 2Text, 3Text, etc.

Obiger Logik zufolge sollten sie sich alle gleich verhalten, da in jedem Fall die gleiche Anzahl an Bits aus dem Symbolraum gelesen und geschrieben werden müssen. Hier ist das Ergebnis:

PL with different data types, 1c, 1000r, 100dv

Die Float und Integer Vorgänge liegen ungefähr gleichauf, aber beide sind 80% langsamer als der Text Datentyp. Wieder ein Ergebnis, dass ich nicht erwartet hätte.

Kopieren ohne Preceding Load

Interessehalber habe ich obige Szenarien dann noch mal mit Kopiervorgängen ohne die Preceding Load Schicht getestet. Zunächst wieder die Variation über die Anzahl distinkter Werte:

Copy with Float, 1c, 1000r, 100dv to 1000dv

Und jetzt die Variation über den Datentyp:

Copy with different data types, 1c, 1000r, 100dv

Wie wir sehen ist das Ergebnis für die Anzahl distinkter Werte gleich (eine Abhängigkeit ist nicht zu erkennen), interessanterweise ist aber auch keine eindeutige Abhängigkeit für die Variation über den Datentyp zu erkennen.

Schlussfolgerung

Eine Schlussfolgerung zu finden fällt mir hier schwer. Entweder habe ich etwas an der Art und Weise wie QlikView die Daten verarbeitet noch nicht verstanden oder ich habe woanders einen Fehler gemacht. Aber wenn das Ergebnis immer das Erwartete wäre, bräuchte man ja auch keine Experimente machen ;-)

Wenn Ihr etwas zur Erklärung der Ergebnisse beitragen könnt, freue ich mich auf Kommentare entweder hier im Blog oder im dazu eröffneten Thread in der Qlik Community.

Wenn du diesen Beitrag interessant fandest und den nächsten nicht verpassen möchtest, abonnier doch einfach meinen RSS Feed links.

Vorschau

Vorsicht vor preceding loads!

Einführung

Für alle, die nicht wissen, was preceding loads sind, bieten die folgenden Blog Beiträge einen hervorragenden Einstieg:

https://community.qlik.com/blogs/qlikviewdesignblog/2013/03/04/preceding-load
http://www.quickintelligence.co.uk/preceding-load-qlikview/
http://qlikviewcookbook.com/2014/08/preceding-load-is-elegant/

Die Autoren erwähnen, dass nachdem Sie diese Funktion kennengelernt haben, sie sich gewundert haben wie sie je ohne klargekommen sind. Ich stimme voll und ganz überein: viele Skriptpassagen lassen sich mit Preceding loads elegant, simpel und mit hervorragender Lesbarkeit verwirklichen.

Preceding load Overhead

Man muss sich aber bewusst sein, dass die Übergabe der Daten von einer Ebene zur anderem scheinbar mit einem gewissen Overhead einhergeht. Nehmen wir folgendes fiktives Code Fragment:

No preceding load, several columns, 2 columns

Es werden schlicht Spalten von einer Tabelle in eine andere kopiert und dabei umbenannt. Ausgehend von einer einzigen Spalte ergibt für bis zu fünf Spalten das folgende Ergebnis, eine nette lineare Entwicklung.

result - no preceding load, x columns

Mit einer zusätzlichen Preceding load Schicht, würde das so aussehen (Table 1 hat nur diese beiden Spalten):

Preceding load, several columns, 2 columns

Für dieses Beispiel ergibt sich eine ähnliche lineare Entwicklung, wobei für fünf Spalten allerdings 183% mehr Zeit benötigt werden statt nur 67%.

result - preceding load, x columns

Stellen wir jetzt allerdings die “No preceding load” und die “Preceding load” Varianten gegenüber, sehen wir das ganze Ausmaß der Performance Einbuße.

result - no preceding load vs preceding load, x columns

Eine Spalte mit “Preceding load” braucht bereits 347% mehr Zeit, als ohne. Bei fünf Spalten sind wir bereits bei einem Aufschlag von 656% (1.264% zu 167%).

Test Setup

Table 1 enthält jeweils 1.000 Zeilen zufällig erzeugter Zahlen. Dann wird diese Tabelle in 100 Durchläufen jeweils 100 mal in eine andere kopiert (Kopie in Table2_1, Table2_2 etc.). Also insgesamt 10.000 Kopiervorgänge. Die Zeit für 100 Kopiervorgänge wird in Millisekunden gemessen und dann auf 1 Kopiervorgang runtergebrochen. In jedem der 100 Durchläufe wird zufällig entschieden, welche Variante ausgeführt werden soll. Ich hoffe mit dem all dem genug Zufall erzeugt und die Messintervalle groß genug gestaltet zu haben, um robuste Messwerte zu erzielen.

Wenn sich das Test Setup weiter stabilisiert hat, werde ich dazu einen gesonderten Post veröffentlichen.

Schlussfolgerung

Preceding loads sind ohne Zweifel super praktisch und elegant und jeder Entwickler sollte Sie in seiner Werkzeugkiste haben. Auch über die Auswirkungen auf die Performance sollte man erst mal keine schlaflosen Nächste verlieren. Für die 1.000 Datensätze und 5 Spalten reden wir auf meinem Computer von lächerlichen 0,01 Sek. Differenz. Steigt die Anzahl der Datensätze, steigt damit aber natürlich auch der absolute Einfluss auf die Performance.

10.000 Datensätze: 0,09
100.000 Datensätze: 0,91
1.000.000 Datensätze: 9,11

Und wir wissen alle, dass 1.000.000 Datensätze in einer QlikView Anwendung eher die Regel als die Ausnahme sind.

Vorschau

Nächste Woche untersuchen wir genauer, ob die Performance vom “Datentyp” abhängt (Integer vs. String, wahrscheinlich nicht) oder ob die Anzahl der unterschiedlichen Werte im Feld einen Einfluss hat (was wahrscheinlicher ist).

Wenn du diesen Beitrag interessant fandest und den nächsten nicht verpassen möchtest, abonnier doch einfach meinen RSS Feed links.

Sandro