Optymalizacja wydajności aplikacji

Wprowadzenie

W przypadku małych i średnich aplikacji QlikView zazwyczaj nie ma potrzeby specjalnego uwzględniania kwestii wydajności podczas projektowania aplikacji. Jeśli jednak aplikacja będzie nieodpowiednio zaprojektowana, wraz ze wzrostem ilości danych mogą zacząć się ujawniać ograniczenia czasowe i pamięciowe. Często wystarczy kilka prostych modyfikacji projektowych, aby znacząco poprawić wydajność. W tym dodatku opisano kilka typowych problemów oraz możliwości ich rozwiązywania.

Ogólną wytyczną dla zwiększania wydajności jest przenoszenie problematycznych zadań z obiektów aplikacji do bazy danych obsługiwanej przez skrypty. Często wymaga to pogodzenia się z kompromisem w postaci skrócenia czasu reagowania kosztem zmniejszenia możliwości wykonywania operacji na żądanie. Poniższych zaleceń nie należy traktować jako rozwiązań uniwersalnie korzystnych. Należy z nich korzystać wtedy, gdy poprawiają ogólną wydajność aplikacji lub dają potrzebny w konkretnej sytuacji przyrost wydajności.

Poniżej podano przykłady praktycznych metod rozwiązywania opisanych problemów. Mają one na celu zilustrowanie problemu i wskazanie przydatnych funkcji aplikacji QlikView. Nie da się jednoznacznie wskazać konkretnej metody jako najlepszej, ale kolejność przykładów w pewnym stopniu to sygnalizuje.

If ( Warunek(Tekst),....)

Klauzule If zawierające porównania wartości tekstowych zazwyczaj są mocno obciążające. Możliwe rozwiązania to odwzorowanie tekstu na liczby, na przykład funkcją automatycznego numerowania (patrz przykłady w poprzedniej sekcji), lub przeniesienie porównania do skryptu.

Sprawdzanie ciągów tekstowych jest wolniejsze od sprawdzania liczb. Weźmy wyrażenie:

If (Alfa= ‘ABC’, ‘ABC’, left (Alfa, 2))

Sprawdzenie warunku można by wykonywać bezpośrednio w skrypcie, nie tracąc przy tym elastyczności:

Load

*,

If (Alfa = ‘ABC’, 1, 0) as Flag

resident table_1 ;

Wyrażenie ma teraz postać:

If ( Flag = 1,’ABC’, left (Alfa, 2))

a sprawdzenie warunku jest znacznie prostsze.

Sum ( If (Warunek, ‘NazwaPola’…))

W tym przypadku agregacja jest niezależna od wymiarów tabeli, a wynik jest rozłożony na wymiary tabeli. Do problemu można podejść albo poprzez wykonywanie sprawdzenia warunku w skrypcie, a agregacji w tabeli, albo poprzez przeniesienie całej operacji do skryptu. Można użyć różnych metod np. intervalmatch, group by, peek lub if....then....else.

Wykonywane są tutaj dwa kroki: sprawdzenie warunku i agregacja wyniku. Weźmy poprzedni przykład i dodajmy do niego agregację:

Sum ( If (Alfa= ‘ABC’, Num*1.25 , Num) )

Load

*,

If (Alfa = ‘ABC’, 1, 0) as Flag

resident table_1 ;

Wyrażenie ma teraz postać:

Sum ( If ( Flag = 1, Num* 1.25 , Num ) )

Agregację można też wykonać bezpośrednio w skrypcie:

table_2:

Load

*,

If (Alfa = ‘ABC’, 1, 0) as Flag

resident table_1 ;

table_3:

Load

Alfa,

If ( Flag = 1, Num* 1.25 , Num ) as NewNum

resident table_2 ;

 

table_4:

Load

Alfa,

Sum( NewNum ) as SumNum

resident table_3

group by Alfa ;

Uwaga: Agregacja jest wykonywana po tabeli Alfa, ponieważ to ona jest wymiarem w tym sprawdzaniu warunku.

If ( Warunek, Sum(‘NazwaPola’)..)

Ta konstrukcja została opisana tylko po to, aby podkreślić różnicę z porównaniu z poprzednim przypadkiem. Taka agregacja jest całkowicie kontekstowa i zazwyczaj nie powoduje problemów z wydajnością.

If ( Warunek1, Sum(‘NazwaPola’), If (Warunek2, Sum(‘NazwaPola’)……..

Logika tworzona poprzez zagnieżdżanie instrukcji If...then else... jest zrozumiała, ale jej utrzymywanie może z czasem nastręczać problemów. Widzieliśmy już przypadki obejmujące kilkaset poziomów zagnieżdżania. Przetwarzanie takich konstrukcji pochłania dużo pamięci i czasu procesora. Warunki można często wyeliminować poprzez odpowiednie przekształcenie. Typowym przykładem jest agregacja wyrażenia ilość*cena, gdy cena jest zmienna. Przypadek ten można obsłużyć z użyciem rozszerzonego dopasowania interwałów. Jeśli konieczne jest spełnienie dwóch warunków, np. „A AND B”, sprawdzenie można zastąpić warunkiem „C”.

Przykład:

sum((GAC12_STD_COST * GAC15_EXCHANGE_RATE) * GIV24_DISP_QTY)

Replaces

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

and

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())))))

poprzez odczytywanie pól GAC12_STD_COST i GAC15_EXCHANGE_RATE jako wymiarów zmieniających się powoli.

Korzystanie z rozszerzonej składni prefiksu intervalmatch w celu rozwiązywania problemów z powoli zmieniającymi się wymiarami

Sortowanie tekstu

Aplikacja QlikView automatycznie określa, czy wartość w Polu ma być traktowana jako typ liczbowy (numeric), tekstowy (text), czy ogólny (general). Pola uznane za typ text będą sortowane jako typ text, co jest najwolniejszą operacją sortowania. Można ją ręcznie zastąpić sortowaniem według kolejności ładowania. Jeśli sortowanie list wartości i innych list nie jest potrzebne, należy je wyłączyć.

Program QlikView sortuje alfanumerycznie ciągi znaków zawierające zarówno znaki, jak i liczby. Oznacza to, że liczby są sortowane według wartości, a pozostałe znaki w kolejności ASCII (w odróżnieniu od typowego sortowania wyłącznie w kolejności ASCII). Przykład:

Sortowanie ASCII Sortowanie alfanumeryczne
A1 A1
A10 A4
A11 A5
A30 A6
A4 A10
A5 A11
A6 A30

Dynamiczne nagłówki i obiekty tekstu

Wyrażenia obliczane dynamicznie można umieszczać praktycznie w każdym miejscu, gdzie można wprowadzać tekst. Zasoby niezbędne do obliczenia wyrażenia są jednak zależne od środowiska jego występowania. Wyrażenia w wykresach i tabelach zdefiniowane w oknie dialogowym wyrażeń są obliczane tylko wtedy, gdy obiekt jest widoczny i dane ulegną zmianie. Nie są natomiast obliczane na przykład wtedy, gdy obiekt jest zminimalizowany.

Z kolei jeśli tytuł obiektu jest obliczany, obliczenie będzie wykonywane po każdej zmianie. Są też różne sposoby definiowania warunków pokazywania, warunków obliczenia itp., które również są sprawdzane za każdym razem.

Niektóre wyrażenia są bardziej obciążające od innych, a wraz ze wzrostem częstotliwości sprawdzania stają się jeszcze bardziej obciążające. Wprowadzenie obliczeń asynchronicznych spowodowało przesunięcie miejsca takich zachowań, przez co ich wpływ w używanych aplikacjach mógł się stać bardziej widoczny.

Funkcje czasu, na przykład Now() i Today(), są obliczane za każdym razem, gdy potrzebne jest ponowne przeliczenie. Szczególnie funkcja Now() może być bardzo obciążająca, ponieważ powoduje ponowne obliczanie stanu aplikacji co sekundę.

Na przykład:

If ( ReloadTime()+3>Now(), 'Old Data', 'New Data')

Można by zmienić na:

If ( ReloadTime()+3>Today(), 'Old Data', 'New Data')

Prostym testem jest umieszczenie wyrażeń w polach tekstowych. Następnie można próbować zmiany rozmiaru pola tekstowego zawierającego wywołanie funkcji Now().

Wyzwalacze makr (przy zmianie)

Makra mogą być uruchamiane niemal przez dowolne zdarzenie w aplikacji. Trzeba uważać na zdarzenia kaskadowe lub rekurencyjne, w których jedno zdarzenie wywołuje następne.