openSAP Hanasql2 Week 3 All Slides
openSAP Hanasql2 Week 3 All Slides
openSAP Hanasql2 Week 3 All Slides
By the end of this week, learners will Using the Optimizer for SQLScript Programming in SAP HANA
be able to solve SQLScript
Week 1
performance issues by using
Understanding SAP HANA SQLScript Optimizer
▪ NO_INLINE hint
▪ BIND_AS_PARAMETER function
▪ BIND_AS_VALUE function
Week 2
▪ SQL hints SAP HANA SQLScript Supportability Features
Week 3
Investigating SQLScript Performance Caused by SQL
Final Exam
You can split a long complex query into multiple short queries using table variables.
▪ Helpful to comprehend the logic of SQLScript
▪ Easy to maintain the logic of SQLScript
You can split a long complex query into multiple short queries using table variables.
▪ Helpful to comprehend the logic of SQLScript
▪ Easy to maintain the logic of SQLScript
Inlining feature combines SQL statements with dependency into a single SQL statement by using
“WITH” clause
Inlining feature combines SQL statements with dependency into a single SQL statement by using
“WITH” clause
CALL "get_results"(
IM_CATEGORY => 'Notebooks',
IM_TYPECODE => 'PR',
RESULTS => ?) WITH HINT (SQLSCRIPT_PLAN_PROFILER);
Inlining feature combines SQL statements with dependency into a single SQL statement by using
“WITH” clause
CALL "get_results"(
IM_CATEGORY => 'Notebooks',
IM_TYPECODE => 'PR',
RESULTS => ?) WITH HINT (SQLSCRIPT_PLAN_PROFILER);
Statement #1, #2, #3, and #4 are combined into a single SQL statement
Statement #1 is executed separately and others are combined by the inlining feature
Two statements are executed. The first one is statement #1 and the other is the output of the
inlining feature for statement #2, #3, and #4.
Two statements are executed. The first one is statement #1 and the other is the output of the
inlining feature for statement #2, #3, and #4.
Two statements are executed. The first one is statement #1 and the other is the output of the
inlining feature for statement #2, #3, and #4.
CALL "get_results"(
IM_CATEGORY => 'Notebooks',
IM_TYPECODE => 'PR',
RESULTS => ?) WITH HINT (SQLSCRIPT_PLAN_PROFILER);
Two statements are executed. The first one is statement #1 and the other is the output of the
inlining feature for statement #2, #3, and #4.
CALL "get_results"(
IM_CATEGORY => 'Notebooks',
IM_TYPECODE => 'PR',
RESULTS => ?) WITH HINT (SQLSCRIPT_PLAN_PROFILER);
Two statements are executed. The first one is statement #1 and the other is the output of the
inlining feature for statement #2, #3, and #4.
CALL "get_results"(
IM_CATEGORY => 'Notebooks',
IM_TYPECODE => 'PR',
RESULTS => ?) WITH HINT (SQLSCRIPT_PLAN_PROFILER);
CALL "get_results"(
IM_CATEGORY => 'Notebooks',
IM_TYPECODE => 'PR',
RESULTS => ?) WITH HINT (SQLSCRIPT_PLAN_PROFILER);
CALL "get_results"(
IM_CATEGORY => 'Notebooks',
IM_TYPECODE => 'PR',
RESULTS => ?) WITH HINT (SQLSCRIPT_PLAN_PROFILER);
NO_INLINE of the last statement in a procedure blocks inlining optimization after flattening procedure
CREATE OR REPLACE PROCEDURE "get_results_wrapper"()
AS BEGIN
CALL "get_results"(IM_CATEGORY => 'Notebooks', IM_TYPECODE => 'PR', RESULTS => :RESULT_TAB);
-- Statement#5
SELECT * FROM :RESULT_TAB;
END; Procedure flattening of CALL “get_results”
CALL "get_results_wrapper"() // Explain plan for CALL
Constant
propagation
SQL statement
inlining &
parallelization
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 28
INLINE feature
Key takeaways
open@sap.com
Follow all of SAP
www.sap.com/contactsap
TIMELINE also shows the compilation time of the problematic inner SQL statement is dominant.
Check the comment of the SQL statement to find out how this query is generated.
call "SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEM
Check the comment of the SQL statement to find out how this query is generated.
/* procedure: "SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS2"
variable: ET_MDPS line: 295 col: 11 (at pos 11750), procedure:
"SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS2" variable: LT_RESB
line: 2 col: 9 (at post 1058), procedure:
"SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS2" variable:
LT_RESB_AGG line: 47 col: 9 (post 2870), procedure:
"SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS2" variable:
LT_VBBE_AGG line:59 col: 9 (at post 3387), procedure:
"SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS2" variable:
... ...
21 lt_resb = select
22 matnr, werks, berid, dat00, delkz, plumi, abs(mng01) as mng01
... ...
... ...
"SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MR
"SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEME
call "SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEM
open@sap.com
Follow all of SAP
www.sap.com/contactsap
Constant
propagation
SQL statement
inlining &
parallelization
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 2
BIND_AS_PARAMETER and BIND_AS_VALUE functions
Introduction
With the “constant propagation” rule, the types of the input parameters are propagated into inner
SQL statements.
▪ When “Notebooks” is given for a CALL statement, the inner SQL statement becomes a literal query with the
constant value “Notebook”.
▪ When a parameter is given for a CALL statement, the inner SQL statement becomes a parameterized query.
Parameterized query
▪ Once a compiled query plan is cached, it is re-used. No additional compilation is needed whenever a
parameter value is changed.
▪ An optimal plan is generated for most parameter values, but it can be suboptimal in some cases.
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 10
BIND_AS_PARAMETER and BIND_AS_VALUE functions
Example – Procedure “get_results” again
open@sap.com
Follow all of SAP
www.sap.com/contactsap
How can we find out which SQLScript procedure is Let’s try to collect the SQL Trace first.
problematic?
// turn on SQL Trace
ALTER SYSTEM ALTER CONFIGURATION ('indexserver.ini','DATABASE') SET
('sqltrace', 'trace') = 'on',
('sqltrace', 'internal') = 'true',
...
WITH RECONFIGURE ;
2023-01-01 01:01:01.
100.100.100.10
2023-01-01 01:01:01.
2023-01-01 01:01:01.
100.100.100.10
2023-01-01 01:01:01.
100.100.100.10
MY_STORE JANUARY_202301 20230101
2023-01-01 01:01:01.
100.100.100.10
2023-01-01 01:01:01.
2023-01-01 01:01:01.
100.100.100.10
100.100.100.10
MY_STORE JANUARY_202301
Then you can see which CALL statement was cancelled. The statement-execution-id values should be the same.
2023-01-01 01:01:01.
100.100.100.10
2023-01-01 01:01:01.
2023-01-01 01:01:01.
100.100.100.10
2023-01-01 01:01:01.
100.100.100.10
MY_STORE JANUARY_202301 20230101
2023-01-01 01:01:01.
100.100.100.10
2023-01-01 01:01:01.
2023-01-01 01:01:01.
100.100.100.10
100.100.100.10
MY_STORE JANUARY_202301
Check the cancelled SQL statement in this procedure. But it doesn’t mean this query is problematic.
2023-01-01 01:01:01.
2023-01-01 01:01:01.
100.100.100.10
MY_STORE JANUARY_202301
statement-execution-id
values are the same
…
2023-01-01 01:01:01.
2023-01-01 01:01:01.
100.100.100.10
2023-01-01 01:01:01.
100.100.100.10
MY_STORE JANUARY_202301 20230101
2023-01-01 01:01:01.
100.100.100.10
2023-01-01 01:01:01.
2023-01-01 01:01:01.
100.100.100.10
100.100.100.10
MY_STORE JANUARY_202301
How can we find out which SQLScript procedure is Let’s try to collect the SQL Trace first.
problematic?
Then, how can we find which inner SQL statements Let’s try to check M_ACTIVE_PROCEDURES.
take a long time?
// Run the problematic procedure
// Before the procedure is cancelled, check M_ACTIVE_PROCEDURES
SELECT * FROM M_ACTIVE_PROCEDURES WHERE PROCEDURE_NAME = 'SP_INVENTORY_SNA
PSHOT_JANUARY_202301';
M_ACTIVE_PROCEDURES shows this query takes very long to execute, which was also shown in the SQL
Trace.
/* procedure: "BI_MY_STORE"."SP_INVENTORY_SNAPSHOT_JANUARY_202301" line: 95 col: 1 (at pos 3894) */ insert into "DSLOCAL"."ZTB_INVENTORY"
select
"MANDT",
...
__typed_Integer__($1) as fiscal_week,
...
from "_SYS_BIC"."BI_MY_STORE.Inventory/CV_SUPPLY"
( placeholder."$$P_LastArunDate$$" => __typed_NString__($2, 8), placeholder."$$P_LastPreviewDate$$" => __typed_NString__($3, 8) )
where
LENGTH(WERKS) = 4
And it has three parameters. Their values are shown in SQL Trace.
After checking “BI_MY_STORE.Inventory/CV_SUPPLY”, find out its base table is a multi-store table linked
with dynamic tiering.
/* procedure: "BI_MY_STORE"."SP_INVENTORY_SNAPSHOT_JANUARY_202301" line: 95 col: 1 (at pos 3894) */ insert into "DSLOCAL"."ZTB_INVENTORY"
select
"MANDT",
...
__typed_Integer__($1) as fiscal_week,
...
from "_SYS_BIC"."BI_MY_STORE.Inventory/CV_SUPPLY"
( placeholder."$$P_LastArunDate$$" => __typed_NString__($2, 8), placeholder."$$P_LastPreviewDate$$" => __typed_NString__($3, 8) )
where
LENGTH(WERKS) = 4
It turns out filters that are given as parameters can’t push down to a remote source in dynamic tiering.
/* procedure: "BI_MY_STORE"."SP_INVENTORY_SNAPSHOT_JANUARY_202301" line: 95 col: 1 (at pos 3894) */ insert into "DSLOCAL"."ZTB_INVENTORY"
select
"MANDT",
...
202301 as fiscal_week,
...
from "_SYS_BIC"."BI_MY_STORE.Inventory/CV_SUPPLY"
( placeholder."$$P_LastArunDate$$" => '20230131' , placeholder."$$P_LastPreviewDate$$" => '20230101' )
where
LENGTH(WERKS) = 4
It is executed quickly because constant values are used as filters in a query for the remote source.
How can we find out which SQLScript procedure is Let’s try to collect the SQL Trace first.
problematic?
Then, how can we find which inner SQL statements Let’s try to check M_ACTIVE_PROCEDURES.
take a long time?
/* procedure: "BI_MY_STORE"."SP_INVENTORY_SNAPSHOT_JANUARY_202301" line: 95 col: 1 (at pos 3894) */ insert into "DSLOCAL"."ZTB_INVENTORY"
select
"MANDT",
...
__typed_Integer__($1) as fiscal_week,
...
from "_SYS_BIC"."BI_MY_STORE.Inventory/CV_SUPPLY"
( placeholder."$$P_LastArunDate$$" => __typed_NString__($2, 8), placeholder."$$P_LastPreviewDate$$" => __typed_NString__($3, 8) )
where
LENGTH(WERKS) = 4
In the definition of the procedure, three scalar variables are shown where parameters are.
BI_MY_STORE"."SP_INVENTORY_SNAPSHOT_JANUARY_202301" line: 95
BI_MY_STORE"."SP_INVENTORY_SNAPSHOT_JANUARY_202301" line: 95
open@sap.com
Follow all of SAP
www.sap.com/contactsap
SQL hints
▪ Instructions for the SAP HANA database server
which influence the way a database request is
processed
▪ Typically used to optimize SAP HANA performance
or memory consumption and have no effect on the
result set of the request
SQL hint is added at the end of the combination of the first two SQL statements.
Inlining optimization stops at a statement with a SQL hint.
The last SQL statement is executed separately.
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 8
Using SQL hint in SQLScript
HINT from CALL statement
Allows propagation of a hint into internal SQL CALL HINT_TEST() WITH HINT (USE_HEX_PLAN CASCADE);
statements since SAP HANA2 SPS7 and SAP HANA // Explain Plan for CALL
Allows propagation of a hint into internal SQL CALL HINT_TEST() WITH HINT (USE_HEX_PLAN CASCADE);
statements since SAP HANA2 SPS7 and SAP HANA // Explain Plan for CALL
CASCADE propagates the same HINT into all output SQL statements of SQLScript optimization
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 12
Using SQL hint in SQLScript
Key takeaways
open@sap.com
Follow all of SAP
www.sap.com/contactsap
CALL HINT_TEST();
Once the CALL statement is recompiled, inner SQL statements associated with
table parameters/variables are changed with new GUID values.
SQL hints added/pinned previously no longer work, because the target SQL
statements have changed.
Pinning both CALL statement and inner SQL statement to add hints.
Pinning plans prevents recompilation of a procedure by plan cache eviction.
Week 1
Understanding SAP HANA SQLScript Optimizer
Week 2
Final Exam
open@sap.com
Follow all of SAP
www.sap.com/contactsap