第十一篇.hfm规则入门(四:深入浅出for语句) -凯发app官方网站

凯发app官方网站-凯发k8官网下载客户端中心 | | 凯发app官方网站-凯发k8官网下载客户端中心
  • 博客访问: 58379
  • 博文数量: 18
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 286
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-16 21:41
个人简介

微信公众号:大话epm 10年epm产品线经验,精通hfm/tagetik产品

文章分类

(18)

  • (17)
  • (1)
文章存档

(17)

(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句,不如亲自去实践,写一句看现象,输出结果,相信必有所获,掌握其中的真谛与设计意图。

阅读(5145) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~
")); function link(t){ var href= $(t).attr('href'); href ="?url=" encodeuricomponent(location.href); $(t).attr('href',href); //setcookie("returnouturl", location.href, 60, "/"); }
网站地图