I'm currently trying to perform some SAP analysis regarding licensing. I'd like to link users to transactions through roles they have and get the required licenses based on their transactions. This analysis is performed across multiple SAP Servers with each server containing multiple SAP instances. At one point of this analysis, I struggle with large tables and query optimization since the query is never ending (run more that 10 hours (though I have 128 GB of RAM and big CPU performance).
Here are some details about the tables I based my query on:
- SAP_LICENSING.DBO.calc_2_USER_ROLES which contains 1M rows and is defined by those columns: DTT_ID (SAP Server Name), MANDT (SAP instance name), UNAME (user name), ASSIGNED_ROLE (role he is assigned to, for example : accoutant). This table stores the roles assigned to users
- SAP_LICENSING.DBO.raw_AGR_1251 which contains 2M rows and is defined by those columns : DTT_ID (SAP Server Name), MANDT (SAP instance name), AGR_NAME (role), LOW (transaction range start), HIGH (transaction range end)
- SAP_LICENSING.DBO.param_LICENSING_RULES contains 140K rows and is defined by those columns : TRANSAC (transaction), LICENSE (required license for the related transaction)
I've set clustered index on each of those tables:
- SAP_LICENSING.DBO.calc_2_USER_ROLES: Index on DTT_ID, MANDT, UNAME, ASSIGNED_ROLE
- SAP_LICENSING.DBO.raw_AGR_1251: Index on DTT_ID, MANDT, AGR_NAME, LOW, HIGH
- SAP_LICENSING.DBO.param_LICENSING_RULES: Index on TRANSAC
Here are my response times for a select on each sub query:
- Subquery regarding the UR alias: 30 seconds
- Subquery regarding the T alias: 1 minute and 30 seconds
- Subquery regarding the LR alias: 5 seconds
Please note the following points :
- when running this query, I see a max usage of 10% of CPU and 30% of RAM
- the query works quickly on a subset of SAP servers (filter on 1 SAP server name)
- the second subquery is used to transform SAP transaction range into searchable transactions compatible with a JOIN with the BETWEEN keyword
- the LEFT JOIN is used because I want to keep unmatched transactions for further analysis
Here is the related query I'm struggling with :
INSERT INTO SAP_LICENSING.DBO.calc_3_USER_ROLES_TRANSACTIONS
SELECT UR.DTT_ID,UR.MANDT,UR.UNAME,UR.ASSIGNED_ROLE,
TRANSAC_FROM,TRANSAC_TO,SAP_TRANSAC_RANGE,LR.TRANSAC,LR.LICENSE
--Get User Role Assignments
FROM
(
SELECT DISTINCT UR.DTT_ID,UR.MANDT,UR.UNAME,UR.ASSIGNED_ROLE
FROM SAP_LICENSING.DBO.calc_2_USER_ROLES UR
)UR
--Join on transactions and Convert SAP Transaction ranges into SQL searchable ranges
JOIN
(
SELECT T.DTT_ID,T.MANDT,T.AGR_NAME,T.AUTH,
replace(replace(T.LOW,'*',' '),'$',' ') AS TRANSAC_FROM,
replace(replace(coalesce(T.HIGH,T.LOW),'*',left('ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ',41-len(coalesce(T.HIGH,T.LOW)))),'$','Z') AS TRANSAC_TO,
CONCAT(T.LOW,' TO ', isnull(T.HIGH,'')) as SAP_TRANSAC_RANGE
FROM SAP_LICENSING.DBO.raw_AGR_1251 T
)T
ON UR.ASSIGNED_ROLE=T.AGR_NAME and UR.MANDT=T.MANDT and UR.DTT_ID=T.DTT_ID
--Join on transactions requiring a license
LEFT JOIN SAP_LICENSING.DBO.param_LICENSING_RULES LR
ON LR.TRANSAC between T.TRANSAC_FROM and T.TRANSAC_TO;
Thanks a lot for any help you would give. Kindest Regard