Professional Documents
Culture Documents
Most of the complex BW transformations (even on HANA DB) that requires complex routines are still built based on
ABAP which is executed in the ABAP application server. This constitutes huge performance overhead as the logic in
the transformation are processed row-by-row and field-by-field and data transfer happens twice between the ABAP
application server and the Database.
There has been a tremendous shift on how performance issues are addressed especially when you are now on HANA.
As Jonathan Andre noted on his blog Want to Avoid HANA AMDP Mistakes? READ THIS the rule-of-thumb is: do as
much as you can in the database to gain the best performance! This is what “HANA-pushdown” is all about. There
are several ways to achieve this and one way is via AMPD (ABAP Managed Database Procedure). From a SAP BWoH
perspective and as of SAP BW 7.4 SP6, you can now use AMDP to implement your HANA-based routines in your BW
transformation.
I will be explaining on this in more detail and lastly, will be sharing some of the actual examples I have done in my
previous project. I will go through each of these actual examples, explain what each routine is doing, how it was
implemented in ABAP and how I manage to convert it into AMDP.
HANA-based BW transformation pushes down a transformation logic directly into the HANA database system. HANA
push-down is achieved by:
• Standard Rule Types – When you use only standard formulas, Masterdata and DSO lookup in your BWoH
transformation.
• AMDP (ABAP Managed Database Procedure) – Traditionally, most or all your current BW transformation
routines are written in ABAP. If you want to push the entire transformation routines directly to HDB, you will
need to do this via AMDP which I will be explaining further in this document.
As of SAP BW 7.4 SP6, HANA-transformation is only available through HANA expert routines. While from SAP BW 7.5
SP4, you now have options to push down your transformation logic through Start, Field and End Routines with the
Expert routine already made available since SAP BW 7.4 Sp6.
As mentioned, HANA-pushdown for BW transformation is only available from SAP BW 7.4 SP6. Below are some points
that you need to consider before embarking on HANA-based BW transformation:
• Apply the required notes depending on the minimum version of your environment. You can use the link for
reference - https://wiki.scn.sap.com/wiki/display/BI/HANA+Transformations+-+Troubleshooting
• Strong knowledge in ABAP – You need to have a strong knowledge in ABAP or you need to have a strong
ABAPer with you to understand what the current ABAP-routine is doing.
• Strong HANA SQL scripting knowledge – It is important to gain strong knowledge on SQL scripting as the key
challenge you may face is how you will convert the existing typical ABAP-routines (e.g. Loop statements,
buffering into internal table) into single pure or series of HANA SQL scripts
ABAP-based HANA-based
Transformation Row by Row, Field by Field Package-based processing
Process Transformation Logic is processed Transformation Logic is processed
between ABAP application Server and entirely in HANA DB
DB
Objects Created Generates a standard ABAP Program in Generates the following: AMDP,
the ABAP Application Server Standard Stored Procedure in HANA DB
Required ABAP Scripting HANA SQL Scripting
Knowledge
• Objects Created – ABAP-based generates the corresponding ABAP program while HANA-based generates a
standard HANA Stored procedure in the HANA DB
• Required Knowledge – You will need to develop your HANA SQL scripting should you embark on converting
your ABAP routines to HANA. Again, as mentioned the key challenge would be how to figure out converting
a typical ABAP script into pure SQL (avoiding loops, etc.).
Again, as mentioned, HANA-based transformation routines are implemented via AMDP. I will be discussing more of
this context in the next section.
AMDP is a class-based framework that is provided to push down database intensive processing directly to HANA DB.
Before I go deep further on AMDP let me just give you a background on how HANA push down is done before AMDP.
2.1 How HANA Stored Procedures are called between ABAP and HANA Server
Before AMDP was introduced, what the developers do is they follow a “BOTTOM-UP” approach:
1. The developers will create a standard stored procedure in the HANA DB which will contain databased
intensive processing via SQL scripts
2. The created standard stored procedure will be wrapped in a HANA Delivery Unit in HDB and will be exposed
as a Database Procedure Proxy and transported into the SAP Netweaver Application server through HANA
transport container.
4. So basically, you will need a delivery unit in HDB system and a standard SAP transport in SAP Netweaver to
move your transports across different environment
The following links will give you a good introduction and further learning about AMDP:
https://blogs.sap.com/2014/01/22/abap-managed-database-procedures-introduction/
https://help.sap.com/saphelp_nw74/helpdata/en/3e/7ce62892d243eca44499d3f5a54bff/frameset.htm
When you are creating a HANA-based BW transformation routines (Start, Field, End or HANA-expert routines), the
BW framework generates an AMD class method for you to write your SQL scripts implementation.
This method can only be modified via ADT (ABAP Development Perspective) which is also driven by the BWMT (BW
Modelling tools) in the HANA Studio.
Below are points that needs to be taken into consideration when working on AMDP:
1. You can access available DDIC views and table in your SAP BW system inside an AMDP Method
2. Not all SQL script functions are available in AMDP – you cannot use the full SQL scripting. Based on my
experience, you cannot use “TOP N” and “GROUP BY” clause in a subquery
3. You won’t be able to use Standard/Custom ABAP Function modules (i.e. CONVERT_TO_LOCAL_CURRENCY,
etc.) – alternatively, you can use a corresponding CE Functions or a Native HANA SQL Functions (i.e.
CE_CONVERT, CONVERT_CURRENCY)
Creating a HANA-based BW transformation is almost the same as the usual ABAP-based. The only difference is that
your routines are implemented in AMDP. Follow the steps below:
1. In your HANA studio, open the BW perspective and login to your BW project.
2. Open or create an existing transformation where you want to implement your first HANA-based routine
3. Say, for example in the transformation below, you will need to implement a HANA-based field routine for the
highlighted field.
4. Double-click on this field and you be prompted with enter your source fields as shown below:
5. When you entered the required source field, change the Rule Type to “Routines”. The system will prompt
you to either use ABAP or AMDP script for your routine.
b. Class Implementation – The class generates a Class Method for you to implement you AMDP scripts
Inside this method is where you are going to implement your SQL scripts.
The sample script above is using MARA as a lookup table. Notice the following:
a. OUTTAB = is your RESULT_PACKAGE from an ABAP routine point of view
b. INTAB = is your SOURCE_PACKAGE from and ABAP routine point of view
10. Activate your script by click on the button on top then activate the whole transformation.
11. You now have your first HANA-based transformation!
In this section, I will be sharing some of the actual example I have done in my previous project where I have converted
some of their ABAP routines to HANA via AMDP. I will be explaining each of the routine’s logic and how it was
implemented in ABAP and then how I managed to convert them to HANA. As I have mentioned in section 1.2, dealing
with AMDP involves heavy HANA SQL Scripting. The key challenge that you’ll face is to figure out how to convert an
ABAP routine (e.g. routines with LOOP, buffering data into an internal table, etc.) into pure HANA SQL script.
The first example below is a Field-routine which derives ZRT_STORE from a master data based on the source fields:
PLANT and RETAILSTOREID.
Sample Data:
Given the example source package and in the ZPA_SITE master data above, derive ZSTORE from ZPA_SITE master data
based on the following rules:
1. Rule#1 – Check for the combination from the source package in the master data where RETAILSTOREID =
RT_CUSTPL and PLANT = /BIC/ZPA_SITE. If exist, simply take the value of ZRT_STORE as the output
otherwise, apply Rule#2.
2. Rule#2 – Check from the master data based only on RETAILSTOREID where RETAILSTOREID = RT_CUSTPL.
This will give you multiple stores - take only the first instance of /BIC/ZRT_STORE.
The first three records apply to Rule#2 and only the last record applies to Rule#1.
1. Rule#1 just simply takes /BIC/ZRT_STORE from the master data (/BIC/PZPA_SITE) where RT_CUSTPL =
RETAILSTOREID and /BIC/ZPA_SITE = PLANT.
2. Rule#2 takes only the first instance of /BIC/ZRT_STORE from the master data where RT_CUSTPL =
RETAILSTOREID.
As mentioned earlier compare to ABAP, HANA-based BW transformation is a packaged-based processing. So, this
field-routine is processed once per data package and not record-per-record. The above the script is broken down
based into a multiple result sets in the following local table variables:
1. LOOKUP
The first returned table is the LOOKUP table. This one table will take the result of the following SQL Statements
based on the two rules required in logic:
a. Rule#1:
Take ZRT_STORE from ZPA_SITE master data based on RETAILSTOREID and PLANT.
Based on the example data we have, this will give us one result:
This statement has a sub-query, this sub-query will give you the following dataset based on the
sample data:
Noticed that in the sub-query, I used RANK() function to give me a row number based on RT_CUSTPL
and /BIC/ZPA_SITE.
Since Rule#2 requires taking only the first instance of ZRT_STORE, the main query takes care of this
by using the condition where Rank = 1. Thus, will give us the following results:
Results for Rule#1 and Rul#2 are merged using the UNION clause. Below is the result for the LOOKUP table:
Based on this SQL script this will give us the final result:
This next example is a START routine written in ABAP based on the following rules:
1. Restrict the source package records only for Sales Org based on the Sales Org entries in the BW Parameters
Master Data (ZPARAM) using parameter key = ‘ZASRECO2_SALESORG*’.
2. Exclude void transactions (ZRPA_VOID = ‘X’)
So, based on the entries in the master data, you’ll restrict the records in the source package only for Sales Orgs: 5000
to 5999; 6000 to 6999.
In the ABAP routine above, it uses either parameter key “ZASRECO2_SALESORG%” or “AM_SALESORG%” to get the
Sales Orgs values to restrict. There is a LOOP statement in the routine to apply the restriction.
And finally, it also removes all void transactions.
You can also us local scalar variables in HANA SQLscript. In the above script, I used the “Declare” keyword to declare
variables for: lv_param – which holds the parameter key and v_count - which takes the number of records. So, the
script above does the following:
1. First, check which parameter key exist in the ZPARAM master data. Check for ZASRECO2_SALESORG
otherwise use AM_SALESORG.
2. The ZPARAM master data will give you SALES ORG entries based on our example:
3. These records are passed into the local table variable – it_param.
4. The final output which sits in the local table OUTTAB has the following restrictions:
a. A sub-query to restrict SALES ORG from the it_param local table
b. Exclude void transaction (a.”/BIC/ZRPA_VOID” <> ‘X’)
The third example is a START Routine that generates a sequence number for each POS transaction with discount
coupons applied in a store.
In the example source package below, POS transactions 123 and 124 (RPA_TNR = 123, 124) for stores 001 and 003
(/BIC/ZRT_STORE = 001, 002) has discount coupons (RPA_DID <> “”). And only transaction 125 (RPA_TNR = 125) do
not have discounts applied.
Given these POS transactions, generate a sequence numbers (as shown in the above output) for each discount coupon
for every transaction. So, looking at POS transaction 123 (RPA_TNR = 123) under store 001 (/BIC/ZRT_STORE = 001) it
has four discount coupons (RPA_ID = 112, 117, 119, 124). Noticed the output generates sequence numbers 1 to 4
(/BIC/ZRPA_FS = 1, 2, 3, 4). And the rest applies to POS transaction 124.
This part collects all transactions with discounts (RPA_DID <> ‘’) from the source package and pass these
records into the following internal tables:
a. LT_COUPON_COUNT – holds the total number of coupons per transaction and store.
b. LT_COUPON_ID = holds unique records: Transaction (RPA_TNR) + Coupon ID (RPA_DID) + Store
(RT_LOCATIO)
2. Part 2:
This code then generates sequence numbers as required. From the source package, check if there are
transactions with discount coupons from internal table LT_COUPON_COUNT then start generating sequence
numbers from the internal table – LT_COUPON_ID.
The records with coupons and coupon count sits in the new internal table – LT_NEW_RECORDS. Records
from this internal table is processed in part three.
3. Part Three:
All coupon records with corresponding coupon count now sits in LT_NEW_RECORDS. This part deletes the
old ones in the source package table and replace with these new records.
Note that the fields: RT_LOCATIO (from ABAP) and /BIC/ZRT_STORE (AMDP) are the same. The script above is broken
down into two parts which is stored into two staging local tables:
1. COUPONCNT – generates sequence numbers (counters) for every transaction (RPA_TNR) and store
(/BIC/ZRT_STORE). Using the “Rank” function, which provides like a counter for every partition I have defined
in the script.
2. OUTTAB – will be the final output of this script. The local table COUPONCNT is used as a look up table to get
the corresponding counter value.
2. Only go for HANA when dealing with data intensive processing having poor performance
4. Consider the complexity involved for the conversion, the required skill sets, experience and timeframe.
HANA Pushdown via AMDP is a new change of mindset specially if you are used to ABAP application
programming. You need to develop your SQL skills in this area and as I mentioned, you need to find a way
how you can convert complex ABAP routines into SQL when possible
5. Make sure you have enough data to simulate in the Development Environment - enough data to satisfy your
test scenarios
Based on my experience, it’s very difficult to prove your AMDP work in an environment with a very limited
test data. You’ll end up coming up with multiple transports to another environment which has enough data
and this becomes messy in terms of deployment.
6.1 Example #1
if sy-subrc <> 0.
* Select single /BIC/ZRT_STORE into RESULT from /BIC/PZPA_SITE
* where RT_CUSTPL = TRAN_STRUCTURE-RETAILSTOREID and OBJVERS = 'A'.
Select /BIC/ZRT_STORE into RESULT up to 1 rows from /BIC/PZPA_SITE
where RT_CUSTPL = TRAN_STRUCTURE-RETAILSTOREID and OBJVERS = 'A'
order by rt_custpl /bic/zpa_site.
endselect.
endif.
ENDFORM. "/BIC/ZSTORE
METHOD PROCEDURE BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING
/BIC/PZPA_SITE.
-- INSERT YOUR CODING HERE
UNION
ERRORTAB = SELECT '' AS ERROR_TEXT, '' AS SQL__PROCEDURE__SOURCE__RECORD FROM DUMMY WHERE DUMMY <>
'X';
ENDMETHOD.
ENDCLASS.
6.2 Example #2
FIELD-SYMBOLS:
<SOURCE_FIELDS> TYPE _ty_s_SC_1.
DATA:
MONITOR_REC TYPE rstmonitor.
refresh: it_param.
clear: lv_param,
wa_param.
* Get the InfoCube name
* Get the parameter value to restrict the records that are to be loaded
select *
into table it_param
from /BIC/PZPARAM
where /BIC/ZPARAM LIKE lv_param and
OBJVERS = 'A'.
if sy-subrc <> 0.
* Assume US based InfoCubes/ODS
lv_param = 'AM_SALESORG%'.
select *
into table it_param
from /BIC/PZPARAM
where /BIC/ZPARAM LIKE lv_param and
OBJVERS = 'A'.
if sy-subrc <> 0.
exit.
endif.
endif.
* Loop at the data package and then the sales org parameters, if the
* sales org is not between the parameter values delete the record.
LOOP AT l_source_package INTO wa_SOURCE_PACKAGE.
clear: lv_found.
lv_tabix = sy-tabix.
loop at it_param
into wa_param.
ENDLOOP.
SOURCE_PACKAGE[] = t_SOURCE_PACKAGE[].
*$*$ end of routine - insert your code only before this line *-*
ENDMETHOD. "start_routine
if v_count = 0 then
lv_param := 'AM_SALESORG%';
end if;
-- Get the parameter value to restrict the records that are to be loaded
it_param = select * from "/BIC/PZPARAM"
where "/BIC/ZPARAM" LIKE lv_param and OBJVERS = 'A';
if :v_count = 0 then
OUTTAB = SELECT * FROM :inTab Where a."/BIC/ZRPA_VOID" <> 'X';
else
-- Check recods from the sales org parameters, get only those salesorgs within the
parameter values
OUTTAB = select a.*
from :inTab as a
where exists (select b.*
from :it_param as b
where a.salesorg between b."/BIC/ZPARAMVAL"
and b."/BIC/ZPARAMTO")
and a."/BIC/ZRPA_VOID" <> 'X';
end if;
6.3 Example #3
***********************************************************
*Collect Coupon Count Per Transaction
LOOP AT SOURCE_PACKAGE ASSIGNING <SOURCE_FIELDS>.
ENDIF.
ENDLOOP.
*$*$ end of routine - insert your code only before this line *-*
ENDMETHOD. "start_routine
6.4 Example #4
data:
t_price TYPE /BI0/OIPRICE_AVG,
t_month TYPE /BI0/OICALMONTH,
t_year TYPE /BI0/OICALYEAR.
RESULT = t_price.
METHOD PROCEDURE BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT OPTIONS READ-ONLY USING
/BIC/AGIMXXP0300.
-- INSERT YOUR CODING HERE
ERRORTAB = SELECT '' AS ERROR_TEXT, '' AS SQL__PROCEDURE__SOURCE__RECORD FROM DUMMY WHERE DUMMY <>
'X';
ENDMETHOD.