微信公众号:大话epm 10年epm产品线经验,精通hfm/tagetik产品
(18)
(17)
(1)
分类: it职场
2021-07-22 16:16:09
(图片可放大看)
解释上面这段逻辑:
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的设置如下:
上面这段逻辑通常我们都会用到,是规则实现的首选写法,也是初学者入门的学习路径,优点有很多:简单,易于理解,可读性强,方便维护。
但是弊端也很明显,假设, 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循环不能被代替的?
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句,不如亲自去实践,写一句看现象,输出结果,相信必有所获,掌握其中的真谛与设计意图。