Optimalisatie van de programmaprestaties
Inleiding
Bij kleine of middelgrote QlikView-toepassingen hoeft u zich gewoonlijk geen zorgen te maken over het ontwerp van de toepassing in relatie tot de prestaties ervan. Maar als de hoeveelheid gegevens groeit, is het mogelijk dat zowel tijds- als geheugenbeperkingen aan het licht komen in een onjuist ontworpen toepassing. Het is mogelijk met enkele eenvoudige ontwerpwijzigingen de prestaties aanzienlijk te verbeteren. In de bijlage wordt verwezen naar enkele veel voorkomende valkuilen. Daar vindt u er ook oplossingen voor.
In het algemeen worden de prestaties beter als het probleem wordt verplaatst van toepassingsobjecten naar de database die door het script wordt aangedreven. Het is vaak een vestzak-broekzaksituatie. De reactietijd wordt verbeterd en de ad-hocmogelijkheden worden verkleind. De onderstaande aanbevelingen zijn niet zaligmakend. Gebruik deze wanneer ze de algemene staat van de toepassing verbeteren of wanneer ze het verschil betekenen tussen werken en niet werken.
Hieronder vindt u een lijst van voorbeelden van toegepaste methoden voor het oplossen van de hierboven genoemde problemen. Ze zijn bedoeld om de problemen te illustreren en verwijzen u naar bruikbare QlikView-functies. Het is niet mogelijk een algemene aanbeveling te geven als het gaat om de vraag welke methode de beste is, maar de volgorde van de voorbeelden is een aanwijzing.
If ( voorwaarde (tekst),....)
If-clausules waarin tekst wordt vergeleken, zijn gewoonlijk duur. Het kan een oplossing zijn om tekst toe te wijzen aan getallen, bijvoorbeeld met autonumber (zie de voorbeelden in het voorgaande gedeelte) en/of de test in het script uit te voeren.
Het testen van teksttekenreeksen is langzamer dan het testen van numerieke waarden. Overweeg de uitdrukking:
If (Alfa= ‘ABC’, ‘ABC’, left (Alfa, 2))
De test kan ook direct in het script worden uitgevoerd zonder verlies van flexibiliteit.
Load
*,
If (Alfa = ‘ABC’, 1, 0) as Flag
resident table_1 ;
De uitdrukking wordt dan:
If ( Flag = 1,’ABC’, left (Alfa, 2))
en de test is veel eenvoudiger.
Sum ( If (voorwaarde, ‘veldnaam’…))
Hier is de aggregatie onafhankelijk van de tabeldimensies en het resultaat wordt gedistribueerd over de dimensies van de tabel. Het probleem kan worden opgelost door de test in het script uit te voeren en de aggregatie in de tabel, of door de hele handeling in het script uit te voeren. Er zijn talloze technieken hiervoor, zoals interval match, group by, peek of if....then....else.
In dit geval betreft het twee stappen, namelijk het testen van “Condition“ en het aggregeren van het resultaat. Als we het vorige voorbeeld nemen en de aggregatie toevoegen
Sum ( If (Alfa= ‘ABC’, Num*1.25 , Num) )
Load
*,
If (Alfa = ‘ABC’, 1, 0) as Flag
resident table_1 ;
De uitdrukking wordt dan
Sum ( If ( Flag = 1, Num* 1.25 , Num ) )
De aggregatie kan ook direct in het script worden uitgevoerd, als volgt:
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 ;
If ( voorwaarde, Sum(‘veldnaam’)..)
Deze constructie is hier alleen opgenomen om het verschil te benadrukken met de vorige situatie. Deze aggregatie is volledig contextueel en zorgt normaal gesproken niet voor prestatieproblemen.
If ( voorwaarde1, Sum(‘veldnaam’), If (voorwaarde2, Sum(‘veldnaam’)……..
De logica van geneste If...then else... is conceptueel gemakkelijk maar kan vaak moeilijk te beheren worden. Ons zijn gevallen bekend met honderden nestniveaus. Dit legt veel beslag op zowel het geheugen als de processor. De voorwaarden kunnen vaak worden vervangen door ze te transformeren. Een standaardvoorbeeld is de aggregatie quantity*price waarbij "price" variabel is. Dit kan worden omzeild met "extended interval match". Als aan twee voorwaarden, bijvoorbeeld “A EN B” moet worden voldaan, kan de test worden vervangen door een voorwaarde “C“.
Voorbeeld:
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()))
en
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())))))
door de velden GAC12_STD_COST en GAC15_EXCHANGE_RATE te lezen als langzaam veranderende dimensies.
Tekst sorteren
In QlikView wordt automatisch geëvalueerd of een veld moet worden behandeld als numeriek, tekst of algemeen. Velden die worden geëvalueerd als tekst worden gesorteerd als tekst. Dit is de traagste sorteerbewerking. Dit kan worden aangepast zodat handmatig wordt gesorteerd op laadvolgorde. Als het sorteren van keuzelijsten enzovoorts niet nodig is, kunt u dit uitschakelen.
QlikView sorteert tekenreeks van gemengde tekens en getallen in alfanumerieke volgorde. Getallen worden gesorteerd op volgorde van waarde terwijl niet-getallen worden gesorteerd in ASCII-volgorde, in tegenstelling tot bij de traditionele sorteervolgorde waarbij alleen de ASCII-volgorde wordt aangehouden. Voorbeeld:
ASCII-sorteervolgorde | Alfanumerieke sorteervolgorde |
---|---|
A1 | A1 |
A10 | A4 |
A11 | A5 |
A30 | A6 |
A4 | A10 |
A5 | A11 |
A6 | A30 |
Dynamische titels en tekstobjecten
Dynamisch berekende uitdrukkingen kunnen vrijwel overal worden ingevoerd waar ook tekst kan worden ingevoerd. De bronnen die nodig zijn voor de evaluatie van een uitdrukking zijn echter afhankelijk van de omgeving. Uitdrukkingen in grafieken en tabellen die worden gedefinieerd in het uitdrukkingsdialoogvenster, worden alleen berekend wanneer het object zichtbaar is en de gegevens worden gewijzigd. Zij worden bijvoorbeeld niet berekend wanneer het object wordt geminimaliseerd.
Als, aan de andere kant, de objecttitel wordt berekend, wordt deze berekening uitgevoerd telkens als er een verandering optreedt. Er zijn ook vele manieren om toonvoorwaarden, berekeningsvoorwaarden enzovoort te definiëren. Deze testen worden ook te allen tijde uitgevoerd.
Sommige uitdrukkingen zijn duurder dan andere en worden duurder naarmate ze vaker moeten worden geëvalueerd. Met de introductie van asynchrone berekening is het gedrag verschoven en de effecten ervan zijn mogelijk zichtbaar in uw toepassingen.
De tijdfuncties, zoals Now() en Today(), worden geëvalueerd telkens wanneer een herberekening is vereist. Vooral de functie Now() kan kostbaar zijn omdat de toepassing elke seconde opnieuw wordt berekend.
Bijvoorbeeld:
If ( ReloadTime()+3>Now(), 'Old Data', 'New Data')
Hier denkt men bijvoorbeeld aan
If ( ReloadTime()+3>Today(), 'Old Data', 'New Data')
Als eenvoudige test kunt u de uitdrukkingen in tekstobjecten plaatsen. Probeer vervolgens formaat te wijzigen van het tekstobject met Now() erin.
Macroreactieveroorzakers ("BijVerandering")
Macro's kunnen worden gestart door reacties die worden veroorzaakt door tal van gebeurtenissen in de toepassing. Let op voor waterval- of recursieve gebeurtenissen waarbij een gebeurtenis de veroorzaker is van de volgende gebeurtenis die op zijn beurt weer een gebeurtenis in gang zet.