第十一篇.HFM規則入門(四:深入淺出For語句)

oracle_cj發表於2021-07-21

前面我們介紹了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句,不如親自去實踐,寫一句看現象,輸出結果,相信必有所獲,掌握其中的真諦與設計意圖。


我的微信公眾號:大話EPM,歡迎交流


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28963606/viewspace-2782454/,如需轉載,請註明出處,否則將追究法律責任。

相關文章