应用程序性能优化

介绍

使用中等大小或较小的 QlikView 应用程序时,通常不必太担心应用程序的性能设计。如果应用程序设计不良,随着数据量的增长,时间和内存限制可能会变得极为明显。一些简单的设计变更可能会大幅度提高性能。本附录指出了几个常见的陷阱及其补救措施建议。

一般情况下,将应用程序对象的“问题”移至脚本驱动数据库可以提高性能。这是常见的权衡之道。响应时间缩短,临时能力减弱。以下建议不应被视为普遍有利的。当可以改善应用程序的一般状态,或者确保作出或破解稍许差异时,采用这些建议。

以下是处理上述问题的应用方法示例清单。这些示例旨在说明问题并点明有用的 QlikView 功能。我们不可能作出哪种方法最佳的一般性建议,但示例的顺序应有所指点。

If ( Condition(Text),....)

涉及文本对比的 if 子句通常较耗资源。解决方案是将文本映射到数字,例如通过使用自动编号(autonumber)(参阅上节中的示例)及/或在脚本中进行测试。

文本字符串的测试慢于数字测试。考虑以下表达式:

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

测试可直接在脚本中完成,而不会损失任何灵活性。

Load

*,

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

resident table_1 ;

表达式变为

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

测试变得简单得多。

Sum ( If (Condition, ‘FieldName’…))

聚合函数独立于表格维度,结果依据表格维度分配。在脚本内进行测试并在表格内聚合,或者在脚本内执行全部操作,均可解决问题。众多技术均可解决此问题,例如 interval matchgroup bypeek if....then....else 语句等。

本案例涉及两个步骤,即“条件”测试和结果聚合。如果我们采用前述示例,并添加聚合函数

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

Load

*,

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

resident table_1 ;

表达式变为

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

聚合函数也可直接在脚本中完成,如下所示:

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 ;

备注: 聚合函数通过 Alfa 完成,因为这是测试的维度。

If ( Condition, Sum(‘FieldName’)..)

此结构仅包含在此处,以强调与前述例子之间的差异。本聚合函数是完全上下文相关的,一般来说不会导致性能问题。

If ( Condition1, Sum(‘FieldName’), If (Condition2, Sum(‘FieldName’)……..

嵌套式 If...then else... 逻辑语句概念简单,但往往造成管理员的麻烦。我们已见过拥有数百级嵌套的实例。这种语句属内存和 CPU 密集型应用。“条件”(Condition) 往往可以通过转换实现替换。典型的示例是聚合数量*价格(此处价格为变量)。这可通过“扩展性间隔匹配”来处理。如果需要满足两个条件(如"AB" ),则测试可能用条件"C"来替换。

示例:

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

通过读取字段 GAC12_STD_COST 和 GAC15_EXCHANGE_RATE 缓慢更改维度。

另请: 使用扩展的 intervalmatch 语法解决维度变化缓慢问题

文本排序

QlikView 会自动判断字段是处理为数字文本还是一般。判断为文本的字段会按文本进行排序,这是最慢的一种排序方式。这可手动替换为依据加载顺序进行排序。如果不需要列表框等的排序,则将其关闭。

QlikView 混合字符和数字按照字母顺序排序字符串。即数字以数值排序,而非数字以 ASCII 码排序,而不是只有传统的 ASCII 码排序顺序。示例:

ASCII 码排序 字母排序
A1 A1
A10 A4
A11 A5
A30 A6
A4 A10
A5 A11
A6 A30

动态标题和文本对象

动态计算表达式能在任何可输入文本的位置输入。但是表达式评估所需的资源取决于上下文。仅在对象可见且数据更改时计算表达式对话框中定义的图表和表格表达式。例如,不会在对象最小化后计算它们。

另一方面,如果对对象标题进行计算,则每次出现任何改变时均需执行此计算。我们还可以使用众多方法来定义显示条件,计算条件等。这些测试每次都必须执行。

一些表达式占用更多内存,并且评估频率越高,则表达式占用的内存越多。异步计算的引入已经转变了行为,并且这些影响可能会在您的应用程序中变得更加明显。

一旦需要重新计算,则必须验证时间函数(例如 Now(), Today())。由于 Now() 函数会导致每秒重新计算应用程序,因此该函数特别占用内存。

例如:

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

对此用户或许会考虑下式:

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

做个简单的测试,将表达式放入文本框。然后尝试使用内部的 Now() 调整文本框的大小。

宏触发器(“待变更”)

通过设置,宏可为应用程序中发生的任何事件所触发。谨防层叠或递归事件,因为此时一个事件会顺次触发下一个事件。