Logical Partitioning is a very popular modeling pattern in BW. It means instead of storing data in a single InfoCube or DSO distributing the data into several identical InfoCubes or DSOs.
Fig. 1: Logical Partitioning Modeling Pattern
The Logical Partitioning modeling pattern is used to achieve and preserve
The new Semantically Partitioned Object (SPO) feature supports the Logical Partitioning Modeling pattern. The SPO wizard automates building of consistent semantically partitioned InfoCubes and DSOs and guarantees consistent distribution of data into the PartProviders for more information please refer to BW 7.30: Semantically Partitioned Objects
Nevertheless Logical Partitioning may still be challenging even with the new SPO:
To address these challenges the new SPO offers the possibility defining centrally the rules for partitioning i.e. partitioning criteria and values using a BAdI.
This blog gives an introduction about modeling, maintaining and managing your SPOs using the SPO BAdI.
Traditionally logical partitioning modeling is done case by case (tactical logical partitioning). In other words the definition of logical partitions is done for each InfoCube and each DSO individually. Nevertheless the partition characteristic and the partition characteristic values assigned to the PartProviders of different InfoCubes/ DSOs are often identical: e.g. the Sales Order InfoCube is logical partitioned by year resulting into 3 PartProviders storing data of the last 3 years. The same partitioning could apply to purchasing order InfoCubes etc.
The logical partitioning for our little example can be modeled in various ways e.g.
With this simple example we can learn two things (at least):
1. We should not use different logical partitioning implementations for the same requirements of different InfoProviders as this will decrease maintainability and increase costs. Beside this we will have a lot of second best implementations like implementation 1. in the example
2. If partitioning conditions are volatile over time we should not assign fix values but a rule based logical partitioning to remain flexible. The origin of the volatility in our example is in the expression ‘last 3 years’ – with every new year this means that the partition condition will change
If we look to the real world we can learn a third and a forth thing:
3. Assigning partition characteristic values can be quite complex. As shown in figure 1 there is normally no partition criteria characteristic that allows addressing all American or German records directly. Instead we have characteristics like 0COMP_CODE, which serves as partition characteristic what means that we often have to assign a bunch of 0COMP_Code values selecting e.g. the American records for the American PartProvider.
4. Building a logical partitioned InfoCube or DSO in a continuous roll-out situation not all partition characteristic values are known at definition time and often even the final number of PartProviders is not known. That means over time you have to maintain the logical Partitions again and again assigning new values to PartProviders and/ or creating new PartProviders.
Both, 3 and 4, offer a tremendous chance to create erroneous entries and is cumbersome if you want to logical partition multiple InfoCubes and DSOs in the same way.
Again this kind of logical partitioning is rule based in the sense that you can once define centrally the mapping rule of 0COMP_CODE values to Americas and Germany etc Partitions.
We have this situation designing BWs using the Layered Scalable Architecture (LSA).
We can summarize that individual modeling of Logical Partitioned InfoCubes/ DSOs is the second best choice especially with large BWs (EDW) as we have numerous InfoProviders following the same logical partitioning conditions.
The new SPO feature is a big step forward modeling complex partitioning conditions as the new wizard makes the assignment of partitioning characteristics and partitioning characteristic values to semantical partitions (PartProvider) transparent and consistent (DTP filters).
Nevertheless we still have to manually enter the partition characteristic(s) and partition characteristic(s) values for each SPO defining the semantical partitions. Thus with the standard SPO wizard functionality we are confronted with the same challenges mentioned before even though on a higher more comfortable level:
To overcome these challenges the SPO supports a rule based central definition of PartProviders and related DTPs offering the possibility to get all necessary criteria defining PartProviders via a BAdI implementation (BAdI RSLPO_BADI_PARTITIONING).
If we look closer to the SPO definition process we can differ between actively modeled and generated SPO components and assignments:
Fig. 2: SPO Wizard Steps
Actively modeled (the numbers refer to the overview picture above):
Generated:
The SPO with an implementation of the BAdI RSLPO_BADI_PARTITIONING allows to automate the SPO definition and maintenance process beyond standard wizard functionality creating all SPO PartProviders settings and the related DTPs based on central definitions (rules) thus reducing the manual design steps to a minimum.
There are two options addressing the BAdI implementation:
The following picture illustrates the steps where the BAdI can actively support the SPO wizard:
Fig. 3: Interactive SPO modeling using BAdI
Let’s walk thru the SPO using BAdI implementation definition process step by step introducing a simple example.
Example description:
We want to set up an SPO for a DSO that allows distributing Sales Order Header records from a single source with respect to the company which created the records, gathering companies by geographic location. Thus the mapping rule for the partitioning characteristic 0COMP_CODE could be as follows:
Fig. 4: Example-Logical Partitioning by Organization
(The number refer to Figure 3)
We model the SPO Master as usual. The Characteristic 0COMP_CODE is part of the DSO key. Save it.
Fig. 5: Example-Define SPO Master
(The number refer to Figure 3)
We enter the Maintain Partitions screen and are asked to enter the partition Characteristic(s) – here 0COMP_CODE:
Fig. 6: Example-Define SPO Partitioning Characteristic(s)
(The number refer to Figure 3)
Entering the Partition maintenance screen you do not need to enter any partitions or partition characteristic values. These are entered via the BAdI: ‘Build Version From BAdI Implementation’:
Fig. 7: Example- Maintain SPO Partitions using BAdI implementation screen
The result looks as follows:
Fig. 8: Example- SPO Partitions after getting data using BAdI screen
We observe that all SPO PartProviders are defined like given in the mapping table above: names, partition characteristic, partition characteristic values and even the sequence like the partitions are shown.
You have to create a BAdI implementation of the SPO BAdI RSLPO_BADI_PARTITIONING using SE18/ SE19.
The interface IF_RSLPO_BADI_PARTITIONING contains five methods:
Fig. 9: SPO BAdI Methods
The methods GET_T_SPO, GET_T_PART, GET_T_PART_TEXT and GET_T_PART_CRIT return the parameters to define the SPO PartProviders, the method GET_T_PART_DTP returns the parameters to define the DTPs filling the SPO PartProviders.
We have to return the (technical) names of the SPOs that shall be managed using the BAdI
Fig.10: SPO BAdI Method GET_T_SPO
Coding for our example:
method IF_RSLPO_BADI_PARTITIONING~GET_T_SPO.
DATA:
l_spo TYPE rslponame.
* Return a table with names of supported BAdI SPOs.
*
l_spo = 'PSOHD3'.
APPEND l_spo TO r_t_spo.
endmethod.
In our example the name SPO ‘PSOHD3’ is returned.
This method is called for each SPO, which is returned by the first method GET_T_SPO and returns the Partitions and the display position of the Partition.
Fig.11: SPO BAdI Method GET_T_PART
Coding for our example:
method IF_RSLPO_BADI_PARTITIONING~GET_T_PART.
DATA:
l_s_part TYPE rslpo_badi_s_part.
* Return a table with the partitions of SPO I_SPO.
IF i_spo = 'PSOHD3'.
* Valid for SPO with name PSOHD3.
* Partition 01:
l_s_part-idpart = '01'. <<<< Partition Id
l_s_part-posit = 1. <<<< Position Partition
APPEND l_s_part TO r_t_part.
* Partition 02:
l_s_part-idpart = '02'.
l_s_part-posit = 2.
APPEND l_s_part TO r_t_part.
* Partition 03:
l_s_part-idpart = '03'.
l_s_part-posit = 3.
APPEND l_s_part TO r_t_part.
* Partition 04:
l_s_part-idpart = '04'.
l_s_part-posit = 4.
APPEND l_s_part TO r_t_part.
ENDIF.
endmethod.
The method returns for our example SPO ‘PSOHD3’ four Partitions.
This method is called for each SPO, which is returned by the first method GET_T_SPO (other assignments only done here will be ignored) and returns the names / description of the Partitions. The method supports multi-languages.
Fig.12: SPO BAdI Method GET_T_PART_TEXT
method IF_RSLPO_BADI_PARTITIONING~GET_T_PART_TEXT.
DATA:
l_text_d TYPE string,
l_text_e TYPE string,
l_s_part_text TYPE rslpo_badi_s_part_text.
* Return a table with the partition texts of SPO I_SPO.
IF i_spo = 'PSOHD3'.
* Determine partition texts:
* Partition 01:
* German text:
l_s_part_text-idpart = '01'. <<<< for Partition 01
l_s_part_text-langu = 'D'. <<<< language German
l_s_part_text-txtlg = 'APJ Asien, Ozeanien, Japan'.
APPEND l_s_part_text TO r_t_part_text.
* English text:
l_s_part_text-langu = 'E'.
l_s_part_text-txtlg = 'APJ Asia, Pacific, Japan'.
APPEND l_s_part_text TO r_t_part_text.
* Partition 02,03,04...
ENDIF.
endmethod.
This method is called for each SPO, which is returned by the first method GET_T_SPO and returns the partitioncriteria(s) and the assigned values for partitions returned by the method GET_T_PART (other assignments onlydone here will be ignored):
Fig.13: SPO BAdI Method GET_T_PART_CRIT
Coding for our example:
method IF_RSLPO_BADI_PARTITIONING~GET_T_PART_CRIT.
DATA:
l_s_part_crit TYPE rslpo_badi_s_part_crit.
* Return a table with the partitioning criteria.
IF i_spo = 'PSOHD3'.
* Valid for SPO with name PSOHD3.
* Fill partitioning criteria:
l_s_part_crit-iobjnm = '0COMP_CODE'. <<<< Partition characteristic
l_s_part_crit-posit = 1. <<<< 1st Partition characteristic
l_s_part_crit-opt = 'EQ'. <<<< Operator
* Partition 01:
l_s_part_crit-idpart = '01'. <<<< Partition ID
l_s_part_crit-low = 'MY02'. <<<< Partition characteristic value
l_s_part_crit-posit = l_s_part_crit-posit + 1.
APPEND l_s_part_crit TO r_t_part_crit.
l_s_part_crit-low = 'MY08'.
l_s_part_crit-posit = l_s_part_crit-posit + 1.
APPEND l_s_part_crit TO r_t_part_crit.
l_s_part_crit-low = 'MY17'.
l_s_part_crit-posit = l_s_part_crit-posit + 1.
APPEND l_s_part_crit TO r_t_part_crit.
l_s_part_crit-low = 'JP03'.
l_s_part_crit-posit = l_s_part_crit-posit + 1.
APPEND l_s_part_crit TO r_t_part_crit.
l_s_part_crit-low = 'CN17'.
l_s_part_crit-posit = l_s_part_crit-posit + 1.
APPEND l_s_part_crit TO r_t_part_crit.
* Partition 02,03,04…..
ENDIF.
endmethod.
The so far described methods return all information necessary defining the PartProviders of an SPO.
(The number refer to Figure 3)
All SPO Components are generated and activated i.e. all PartProviders, In- and Outbound InfoSources and the (dummy) Transformations between these InfoSources and the SPO PartProviders (s. overview picture above).
(The number refer to Figure 3)
This part is again a ‘creative’ modeling part like the definition of the SPO Master and cannot be automated using the BAdI.
Fig.14: Example - Assign Source InfoProvider
Fig.15: Example - Create Transformations
(The number refer to Figure 3)
Now as the Transformation between Source and SPO InBound InfoSource is active we can create the DTPs between the Source, which is in our example a DSO, and the SPO PartProviders.
When we enter the DTP Generation screen no DTPs are assigned. For a rule-based assignment we call again the BAdI:
Fig.16: Example - Assign DTPs via BAdI
As a result the BAdI returns the DTP assignments:
Fig.17: Example - Assign DTPs via BAdI
We observe that for each PartProvider a DTP from source DSO TSOHD100 is assigned.
Marking the DTPs and pressing ‘Generate’ leads to:
Fig.18: Example - Generate DTPs
Now all the DTPs are generated and the correct filter values are automatically applied:
Fig.19: Example – Automated Filtering in DTPs
This method is called for each SPO, which is returned by the first method GET_T_SPO and returns DTPs and the correct Filter values for partitions returned by the method GET_T_PART (other assignments only done here will be ignored):
Fig.20: SPO BAdI Method GET_T_PART_DTP
Some extracts from BAdi documentation:
1. The name of an existing DTP template must be entered.
2. The type of the specified DTP template must match the TLOGO type TLOGO of the data source. If the data source of the DTP is a DataSource, for example, the DTP template must also be of type DataSource.
Coding for our example:
method IF_RSLPO_BADI_PARTITIONING~GET_T_PART_DTP.
* Return a table with DTPs that are to be generated for new partitions.
data l_s_part_dtp type rslpo_badi_s_part_dtp.
case I_spo.
when 'PSOHD3' .
l_s_part_dtp-idpart = '01'. <<<< Partition ID
l_s_part_dtp-dtptemplate = 'LSA_DSO_SRC'. <<<< DTP template name
l_s_part_dtp-OBJNM = 'TSOHD100'. <<<< Source DSO name
l_s_part_dtp-tlogo = 'ODSO'. <<<< Type of source (TLOGO)
APPEND l_s_part_dtp to r_t_part_dtp.
l_s_part_dtp-idpart = '02'.
l_s_part_dtp-dtptemplate = 'LSA_DSO_SRC'.
l_s_part_dtp-OBJNM = 'TSOHD100'.
l_s_part_dtp-tlogo = 'ODSO'.
…….
endcase.
endmethod.
Fig.21: Example – Workbench view on BAdI created Partitions
We have seen that the SPO wizard in conjunction with the BAdI implementation highly automates the SPO creation process. The BAdI allows the central definition of any kind of rules that offer the parameters for SPO PartProvider and DTP assignments (DTP automated generation is planned). This highly increases development efficiency if multiple different SPOs follow the same semantical partitioning criteria as we have to define the criteria only once. Beside this the overall consistency of our model increases considerably. This becomes evident if you structure your BW applying BW Layered Scalable Architecture (LSA) principles as semantical partitioning (Domains) is done strategically for the large parts or even the entire BW.
With respect to our example I want to emphasize that it is just a simple one illustrating the basic behavior of the BAdI. In general it is not recommended hard coding the SPOs and the parameters in the methods! Instead you should store the parameters in central user defined tables making partitioning criteria reusable for multiple different SPOs! Doing this means just updating your central tables if the Partitions for a new SPO shall be generated using the BAdI.
Beside the consistent creation of SPO Partitions the BAdI helps to maintain the Partitioning if it changes over time. First of all you can change the partitioning criteria and values for a PartProvider without restrictions as long as a PartProvider is empty. Let’s have a look what it means if data have been already loaded to the PartProviders:
Last but not least the BAdI PartProvider definitions overrule all manual changes to the Partitioning done in the SPO wizard! This is by itself a very strong feature as it guarantees the consistency of all BAdI managed SPOs with respect to the central definitions throughout the BW!
We notice that so far applying any expansion or change to existing SPO PartProviders using the BAdI is done calling the SPO Wizard for each SPO affected. This may mean still a lot of manual work in case we want to change a large number of SPOs and implies the danger that we might forget an SPO to maintain.
Thus there is a need for applying changes to a large number of BAdI managed SPOs in an automated manner and this leads us to our next chapter.
The Transaction RSLPO_MASS_ACT allows maintaining all BAdI managed SPOs (returned by method GET_T_SPO) centrally.
RSLPO_MASS_ACT compares the BAdI (methods GET_T_PART, GET_T_PART_TEXT, GET_T_PART_CRIT) returned SPO definition with the active version of these SPOs and lists whether there are differences:
Fig.22: Example – RSLPO_MASS_ACT screen
In detail the status highlights New Partitions, Deleted Partitions and Changed Partitions.
You can now select any set of BAdI managed SPOs and apply the new BAdI settings in a mass change and activation run.
RSLPO_MASS_ACT allows reducing the SPO interactive modeling to an absolute minimum for all SPOs managed via BAdI in case of
RSLPO_MASS_ACT functionality therefore perfectly addresses the volatile logical partitioning challenges mentioned above applying changes consistently throughout your BW.
If we look to our above introduced example it fits perfect to a market by market rollout what we often find with large BWs. Going live with a new market (e.g. with Germany – s. below) may mean adding company-codes to existing PartProviders of a large number of SPOs following the same partition criteria or creating new PartProviders. Let’s assume Germany gets an own PartProvider:
Fig.23: Example – extension
E.g. in our simple example the method GET_T_PART_CRIT – (returns Partitioning Criteria (partition characteristic(s) & values)) just has to be extended adding Partition 05:
method IF_RSLPO_BADI_PARTITIONING~GET_T_PART_CRIT.
DATA:
l_s_part_crit TYPE rslpo_badi_s_part_crit.
* Return a table with the partitioning criteria.
IF i_spo = 'PSOHD3'.
* Valid for SPO with name PSOHD3.
* Fill partitioning criteria:
l_s_part_crit-iobjnm = '0COMP_CODE'.
l_s_part_crit-posit = 1.
l_s_part_crit-opt = 'EQ'.
* Partition 01,02,03,04 unchanged
*
* Partition 05:
l_s_part_crit-idpart = '05'. <<<<<<<< new entries
l_s_part_crit-low = 'DE12'. <<<<<<<< new entries
l_s_part_crit-posit = 1. <<<<<<<< new entries
APPEND l_s_part_crit TO r_t_part_crit. <<<<<<<< new entries
l_s_part_crit-low = 'DE18'. <<<<<<<< new entries
l_s_part_crit-posit = l_s_part_crit-posit + 1.<<<<<<<< new entries
APPEND l_s_part_crit TO r_t_part_crit.
ENDIF.
endmethod.
Calling RSLPO_MASS_ACT the BAdI detects that for our example SPO ‘PSOHD3’ a Partition is returned that does not exist in the active version of ‘PSOHD3’.
Fig.24: Example – RSLPO_MASS_ACT version comparison
Executing RSLPO_MASS_ACT for ‘PSOHD3’ creates the new Partition:
Fig.25: Example – Centrally running RSLPO_MASS_ACT
The result of centrally maintaining the SPO ‘PSOHD3’ with RSLPO_MASS_ACT:
Fig.26: Example – RSLPO_MASS_ACT – new German partition as result
If you imagine that you may have to add this German Partition to multiple SPOs you immediately realize the increase of quality in terms of consistent modeling and the decrease of TCD (Total Cost of Development).
As described above logical partitioning by time is a frequently used modeling pattern. If we logically partition multiple InfoProviders using the same time partition criteria we can define the rule via the BAdI implementation and apply it consistently to multiple SPOs:
Let’s assume we partition InfoCubes or DSOs by time e.g. 0CALYEAR with the option e.g. keeping data only of the actual-year, actual-year-1 and actual-year-2. Data older than 3 years shall be deleted automatically. Using the BAdI we can define a simple rule directing the data of a new year to a new partition and dropping old data, which run out of scope without having more than always 4 PartProviders. The picture illustrates the basic BAdI rule settings:
Fig.27: Example – SPO BAdI and Rolling Window scenario I
The result of running RSLPO_MASS_ACT once a year is shown in the next pictures:
Fig.28: Example – SPO BAdI and Rolling Window scenario II
Fig.29: Example – SPO BAdI and Rolling Window scenario II
A SPO BAdI rule managed Rolling Window scenario resolves the tasks
The SPO Wizard is a powerful feature modeling logically partitioned InfoCubes and DSOs. With complex and volatile partitioning conditions you should consider using the BAdI RSLPO_BADI_PARTITIONING and define the partition criteria and rules centrally. All compatible (s. above) changes to BAdI managed SPOs can then be applied by the Transaction RSLPO_MASS_ACT. This decreases TCD (Total Cost of Development) and increases the overall quality (consistency) of your BW.
The BAdI RSLPO_BADI_PARTITIONING in conjunction with the Transaction RSLPO_MASS_ACT will play a fundamental role automating the implementation and maintenance of SPOs guaranteeing consistency of the logical partitions throughout your BW.