Optimisation des performances de l'application
Introduction
Avec des applications QlikView de taille petite ou moyenne, vous n'avez pas normalement à vous inquiéter des conséquences de la conception de l'application en termes de performances. Si l'application est mal conçue, en revanche, les contraintes de temps et de mémoire peuvent devenir évidentes au fur et à mesure que la quantité de données augmente. Il est possible que certaines modifications simples de la conception améliorent considérablement les performances. Cette annexe relève quelques pièges communs et y propose quelques remèdes.
En général, on améliore les performances en déplaçant le « problème » des objets de l'application à la base de données gérées par le script. C'est souvent une situation de compromis. En effet, le temps de réponse est ainsi amélioré mais les possibilités ad hoc réduites. Les recommandations ci-dessous ne peuvent pas être considérées comme toujours valables. Utilisez-les lorsqu'elles améliorent l'état général de l'application ou quand elles font cette petite différence qui compte.
Ce qui suit est une liste d'exemples des méthodes appliquées pour traiter les problèmes ci-dessus. Ils ont pour but d'illustrer le problème et d'indiquer des fonctions utiles de QlikView. On ne peut pas savoir avec certitude quelle méthode est la meilleure, mais l'ordre des exemples est déjà une indication.
If ( Condition(Texte),....)
Les clauses if impliquant des comparaisons de texte diminuent généralement les performances. Les solutions peuvent être de mapper le texte à des nombres en utilisant par exemple autonumber (voir les exemples de la section précédente) et/ou de faire le test dans le script.
La comparaison de chaînes textuelles est plus lente que la comparaison numérique. Prenez l'expression :
If (Alfa= ‘ABC’, ‘ABC’, left (Alfa, 2))
Le test pourrait être effectué directement dans le script sans perdre en souplesse.
Load
*,
If (Alfa = ‘ABC’, 1, 0) as Flag
resident table_1 ;
L'expression devient :
If ( Flag = 1,’ABC’, left (Alfa, 2))
et le test est beaucoup plus simple.
Sum ( If (Condition, 'Nomdechamp'…))
Ici, l'agrégation est indépendante des dimensions de la table et le résultat est réparti sur ces dimensions. Le problème peut être traité soit en faisant le test dans le script et en l'agrégeant dans la table, soit en faisant toute l'opération dans le script. Il existe de nombreuses techniques pour cela, telles que interval match, group by, peek, if....then....else.
Ce cas implique deux étapes, à savoir le test de la « condition » et l'agrégation du résultat. Si nous reprenons l'exemple précédent et ajoutons l'agrégation
Sum ( If (Alfa= ‘ABC’, Num*1.25 , Num) )
Load
*,
If (Alfa = ‘ABC’, 1, 0) as Flag
resident table_1 ;
L'expression devient
Sum ( If ( Flag = 1, Num* 1.25 , Num ) )
L'agrégation peut aussi être effectuée directement dans le script de la façon suivante :
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 ( Condition, Sum('Nomdechamp')..)
Cette construction est incluse ici uniquement pour souligner la différence avec le cas précédent. Cette agrégation est en effet complètement contextuelle et ne cause généralement pas de problème de performances.
If ( Condition1, Sum('Nomdechamp'), If (Condition2, Sum('Nomdechamp')……..
La logique de la fonction If...then else... imbriquée est facile à comprendre, mais peut souvent devenir compliquée à gérer. Nous avons vu des cas comportant des centaines de niveaux d'imbrication. Cela exige à la fois beaucoup de mémoire et beaucoup de travail de l'unité centrale. Les « conditions » peuvent souvent être transformées. Un exemple courant est d'agréger quantité*prix quand le prix est variable. On peut le faire grâce au préfixe « interval match étendu ». Si deux conditions, par exemple « A ET B » doivent être réalisées, le test peut être remplacé par une condition « C ».
Exemple :
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())))))
en lisant les champs GAC12_STD_COST et GAC15_EXCHANGE_RATE comme des dimensions changeant progressivement.
Trier du texte
QlikView évalue automatiquement si un champ doit être traité comme numérique, texte ou général. Les champs évalués comme du texte seront triés en tant que texte, c'est-à-dire l'opération de tri la plus lente. On peut demander manuellement à les trier par ordre de chargement. Si le tri des listes de sélection, etc. n'est pas nécessaire, désactivez-le.
QlikView trie par ordre alphanumérique les chaînes composées à la fois de caractères et de nombres. Autrement dit, les nombres sont triés par ordre de valeur tandis que les caractères autres que des chiffres sont triés par ordre ASCII, par opposition à l'ordre de tri ASCII seul classique. Exemple :
Tri ASCII | Tri alphanumérique |
---|---|
A1 | A1 |
A10 | A4 |
A11 | A5 |
A30 | A6 |
A4 | A10 |
A5 | A11 |
A6 | A30 |
Légendes et objets texte dynamiques
On peut saisir des expressions calculées de façon dynamique presque partout où l'on peut saisir du texte. Les ressources requises pour l'évaluation d'une expression dépend toutefois de son environnement. Les expressions des graphiques et des tableaux qui sont définies dans la boîte de dialogue des expressions ne sont calculées que quand l'objet est visible et que les données changent. Elles ne sont pas calculées, par exemple, quand l'objet est réduit.
Par ailleurs, si le titre de l'objet est calculé, ce calcul est effectué à chaque fois qu'un changement intervient. Il existe aussi de nombreuses manières de définir des conditions d'affichage, des conditions de calcul, etc. Ces tests seront aussi effectués en permanence.
Certaines expressions diminuent davantage les performances que d'autres et ce d'autant plus qu'elles doivent être évaluées fréquemment. L'introduction d'un calcul asynchrone a modifié le comportement de vos applications et ces effets y sont peut-être devenus ainsi plus flagrants.
Les fonctions de temps, comme Now() et Today(), seront évaluées à chaque fois qu'un recalcul sera requis. La fonction Now() surtout peut diminuer beaucoup les performances, car elle provoque le recalcul de l'application toutes les secondes.
Par exemple :
If ( ReloadTime()+3>Now(), 'Old Data', 'New Data')
Ici, on peut prendre
If ( ReloadTime()+3>Today(), 'Old Data', 'New Data')
En guise de test, mettez les expressions dans des zones de texte. Puis, essayez de dimensionner la zone de texte qui contient Now().
Déclencheurs de macros (« en cas de modification »)
On peut définir des macros à déclencher presque à chaque événement survenant dans l'application. Faites attention aux événements en cascade ou récursifs où un événement déclenche le suivant, qui à son tour.