Chinaunix首页 | 论坛 | 博客
  • 博客访问: 60971
  • 博文数量: 18
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 286
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-16 21:41
个人简介

微信公众号:大话EPM 10年EPM产品线经验,精通HFM/Tagetik产品

文章分类
文章存档

2021年(17)

2013年(1)

分类: IT职场

2021-07-22 16:16:09

  前面我们介绍了exp函数的使用,笔者非常建议读者认真阅读官方文档关于exp函数的经典使用。这篇介绍H FM 规则中的For语句,f or 循环的用法在任何语言中表达的含义都是一样的,循环扫描集合进行逻辑处理,在H FM 规则中也不例外。
    For语句,笔者对它是又爱又恨,for语句实现逻辑简单明了,可读性强,是初学者的必然选择。但是For循环也是性能杀手,我们说HFM
运行计算或者合并耗时,产生性能问题,往往都是f or 循环在作祟。但是有的场景,比如很多时候我们要扫码I CP 维度时,就必须要用for循环,而且似乎没有可替代的优化手段。

一、for循环的简单应用

先来看下面的一段常规的for循环使用逻辑:

(图片可放大看)


解释上面这段逻辑:

1、首先规则一定要规范,比如规范的变量定义,初始化,以及必要的注释和语句的缩进。很多人刚开始学的时候不注意,规则写的非常的乱,一旦规则的堆积如山的时候,发现可读性极差,读者千万不要小看这些细节。良好的规范可以增强可读性,减少后期维护量以及供别人使用时能快速了解逻辑。

2、5050-5059行是对两个变量的定义以及初始化,其中strSourceMemeber是源POV,也即数据源,一般是各个维度的顶级成员(Total),strTargetMember01是目标POV,用来写数据的,各个维度的base成员([None])

3、5061-6064行是扫描AccountList这个父项的Base成员,然后进行计算前清数

4、5069-5084行,扫描ICP维度和科目维度进行了两层循环,将每个科目的每个ICP维度上的数据累加,放到ICP01这个ICP成员上

5、科目和ICP的设置如下:


二、for循环的优化

       上面这段逻辑通常我们都会用到,是规则实现的首选写法,也是初学者入门的学习路径,优点有很多:简单,易于理解,可读性强,方便维护。

但是弊端也很明显,假设, AccountList 下面的成员有1000个, [ICP Entities] 下面有5000个成员,那么双层循环扫描的代价就是:1000*5000的量级,也就是说不管科目与ICP维度的组合是否有数据,上面的逻辑都会扫描所有科目和所有ICP成员,这样就会消耗系统大量资源,尤其在高并发的场景时,会产生性能问题,导致系统运行缓慢,甚至卡死。

       针对上面这种写法,我们常用的一种优化方式就是使用HFM提供的OpenDataUnit函数,这也是进阶写法。

改进后的写法如下:

我们仍然作几点解释:

1)1772-1783行与前面逻辑一致,不做赘述

2)1786行使用了HFM内置函数OPENDATAUNIT进行结果集的获取,对于单个维度成员引用直接使用”短名称#维度成员”即可,但是对于维度集合的使用,必须用大括号,如科目:A{AccountList.[Base]}这样的写法。这么写的优点就是一次性将有数据的科目和ICP过滤出来,维度组合上没有数据的不会出现在结果集中。这样就大大减少了集合的数量级。

3)1788-1800行就是对有数据的组合进行使用,比如我们可以只处理dData<>0的数据

三、结论

1)、如果想要写出高效的规则,非常建议使用HFM内置的函数。具体可参考官方文档中的规则函数部分。

2)、对于初学者来说,规则入门建议从for循环这种基本写法开始,后续再根据情况升级写法。

3)、前面提到for循环有优点,也有缺点,需要根据具体情况针对使用,有的业务场景必须要用for循环,使用如opendataunit函数是不能代替的,读者试想下,哪种情况是for循环不能被代替的?

四、有关OpenDataUnit的思考

1)使用OpenDataUnit函数代替可以大幅提升规则效率,尤其是在科目和ICP量级比较大的时候,效率可提升50%+,具体可根据实际情况进行测试。

2)OpenDataUnit的底层应该是将POV组合条件在数据库中将查询出有数据的组合,然后将结果集返回,最后去扫描结果集进行逻辑处理。而不像for循环一样,需要逐条去读取数据库的数据。

3)OpenDataUnit函数中,假设以科目为例,当使用 A{AccountList.[Children]}时,意思是取AccountList的直接子代,结构如下:

A{AccountList.[Children]} 成员列表,获取的结果是:122101,122102, 122103 ,122104,122105,其中 122103 是一个父级科目。 当我们使用如下语句:Dataunit.item(i).Account时是获取不到 122103 这个科目的

笔者以前没有注意过这个现象,读者可去试试,欢迎来讨论结果。

所以笔者认为用成员列表获取数据时是只能读取base级别,在OpenDataUnit中如果使用了成员列表,取到的是base数据,想要获取父级数据,要用A#122103单个科目的写法。

4、最后总结还是这一句,读者看5句,不如亲自去实践,写一句看现象,输出结果,相信必有所获,掌握其中的真谛与设计意图。

阅读(5258) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~