Week 3: Investigating SQLScript Performance Caused by SQL
Unit 1: INLINE Feature
INLINE feature
Learning objectives
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
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 2
INLINE feature
Introduction – Table variable
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
From a performance perspective, using table variables could be suboptimal.
Executing multiple short queries
Executing a single long complex query
with table variables
vs.
1. Multiple calls to SQL engine 1. Single call to SQL engine
2. Multiple copies for result set values 2. Benefit more from SQL optimizer
3. Less materialization of intermediate results
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 3
INLINE feature
Introduction – Inlining
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 retains two advantages. 2 Executing a single long complex query
SQLScript optimizer converts multiple short queries
associated with table variables into a single query.
1. Single call to SQL engine
2. Benefit more from SQL optimizer
3. Less materialization of intermediate results
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 4
INLINE feature
Example – Procedure “get_results”
CREATE PROCEDURE "get_results"(
IN im_category VARCHAR(40), IN im_typecode VARCHAR(2),IN im_start_date DATE DEFAULT '2022-06-02', IN im_end_date DATE DEFAULT '2022-08-31',
OUT RESULTS TABLE (PRODUCTID NVARCHAR(10), RESULTDATE DAYDATE, NUM_RESULT BIGINT)
) AS BEGIN
-- Statement#1
final_products = SELECT * FROM "Products_A" WHERE category = :im_category AND typecode = :im_typecode;
-- Statement#2
items = SELECT i."PRODUCTID" AS PRODUCTID, i."DELIVERYDATE" AS RESULTDATE FROM :final_products AS p INNER JOIN "Item_A" AS i ON p.productid =
i."PRODUCTID" WHERE i.DELIVERYDATE >=:im_start_date AND i.DELIVERYDATE <= :im_end_date;
-- Statement#3
aggregated_items = SELECT PRODUCTID, RESULTDATE, COUNT(PRODUCTID) AS NUM_RESULT FROM :items GROUP BY PRODUCTID, RESULTDATE;
-- Statement#4
RESULTS = SELECT * FROM :aggregated_items ORDER BY PRODUCTID, RESULTDATE;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 5
INLINE feature
Dependency in procedure “get_results”
Dependency between statement #1 and #2
CREATE PROCEDURE "get_results"(
IN im_category VARCHAR(40), IN im_typecode VARCHAR(2),IN im_start_date DATE DEFAULT '2022-06-02', IN im_end_date DATE DEFAULT '2022-08-31',
OUT RESULTS TABLE (PRODUCTID NVARCHAR(10), RESULTDATE DAYDATE, NUM_RESULT BIGINT)
) AS BEGIN
-- Statement#1
final_products = SELECT * FROM "Products_A" WHERE category = :im_category AND typecode = :im_typecode;
-- Statement#2
items = SELECT i."PRODUCTID" AS PRODUCTID, i."DELIVERYDATE" AS RESULTDATE FROM :final_products AS p INNER JOIN "Item_A" AS i ON p.productid =
i."PRODUCTID" WHERE i.DELIVERYDATE >=:im_start_date AND i.DELIVERYDATE <= :im_end_date;
-- Statement#3
aggregated_items = SELECT PRODUCTID, RESULTDATE, COUNT(PRODUCTID) AS NUM_RESULT FROM :items GROUP BY PRODUCTID, RESULTDATE;
-- Statement#4
RESULTS = SELECT * FROM :aggregated_items ORDER BY PRODUCTID, RESULTDATE;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 6
INLINE feature
Dependency in procedure “get_results”
Dependency between statement #2 and #3
CREATE PROCEDURE "get_results"(
IN im_category VARCHAR(40), IN im_typecode VARCHAR(2),IN im_start_date DATE DEFAULT '2022-06-02', IN im_end_date DATE DEFAULT '2022-08-31',
OUT RESULTS TABLE (PRODUCTID NVARCHAR(10), RESULTDATE DAYDATE, NUM_RESULT BIGINT)
) AS BEGIN
-- Statement#1
final_products = SELECT * FROM "Products_A" WHERE category = :im_category AND typecode = :im_typecode;
-- Statement#2
items = SELECT i."PRODUCTID" AS PRODUCTID, i."DELIVERYDATE" AS RESULTDATE FROM :final_products AS p INNER JOIN "Item_A" AS i ON p.productid =
i."PRODUCTID" WHERE i.DELIVERYDATE >=:im_start_date AND i.DELIVERYDATE <= :im_end_date;
-- Statement#3
aggregated_items = SELECT PRODUCTID, RESULTDATE, COUNT(PRODUCTID) AS NUM_RESULT FROM :items GROUP BY PRODUCTID, RESULTDATE;
-- Statement#4
RESULTS = SELECT * FROM :aggregated_items ORDER BY PRODUCTID, RESULTDATE;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 7
INLINE feature
Dependency in procedure “get_results”
Dependency between statement #3 and #4
CREATE PROCEDURE "get_results"(
IN im_category VARCHAR(40), IN im_typecode VARCHAR(2),IN im_start_date DATE DEFAULT '2022-06-02', IN im_end_date DATE DEFAULT '2022-08-31',
OUT RESULTS TABLE (PRODUCTID NVARCHAR(10), RESULTDATE DAYDATE, NUM_RESULT BIGINT)
) AS BEGIN
-- Statement#1
final_products = SELECT * FROM "Products_A" WHERE category = :im_category AND typecode = :im_typecode;
-- Statement#2
items = SELECT i."PRODUCTID" AS PRODUCTID, i."DELIVERYDATE" AS RESULTDATE FROM :final_products AS p INNER JOIN "Item_A" AS i ON p.productid =
i."PRODUCTID" WHERE i.DELIVERYDATE >=:im_start_date AND i.DELIVERYDATE <= :im_end_date;
-- Statement#3
aggregated_items = SELECT PRODUCTID, RESULTDATE, COUNT(PRODUCTID) AS NUM_RESULT FROM :items GROUP BY PRODUCTID, RESULTDATE;
-- Statement#4
RESULTS = SELECT * FROM :aggregated_items ORDER BY PRODUCTID, RESULTDATE;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 8
INLINE feature
Output of inlining – Explain plan for CALL
Inlining feature combines SQL statements with dependency into a single SQL statement by using
“WITH” clause
DELETE FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'INLINE';
EXPLAIN PLAN SET STATEMENT_NAME = 'INLINE' FOR
CALL "get_results"(
IM_CATEGORY => 'Notebooks',
IM_TYPECODE => 'PR',
RESULTS => ?);
SELECT * FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'INLINE';
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 9
INLINE feature
Output of inlining – 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);
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 10
INLINE feature
Output of inlining feature – 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);
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 11
INLINE feature
Output of inlining – Formatted SQL statement
Statement #1, #2, #3, and #4 are combined into a single SQL statement
CREATE PROCEDURE "get_results"(
IN im_category VARCHAR(40), IN im_typecode VARCHAR(2),IN im_start_date DATE DEFAULT '2022-06-02', IN im_end_date DATE DEFAULT '2022-08-31',
OUT RESULTS TABLE (PRODUCTID NVARCHAR(10), RESULTDATE DAYDATE, NUM_RESULT BIGINT)
) AS BEGIN
WITH
"_SYS_FINAL_PRODUCTS_2" AS
(SELECT * FROM "Products_A" WHERE category = CAST(N'Notebooks' AS NVARCHAR(40)) AND typecode = CAST(N'PR' AS NVARCHAR(2)) ),
"_SYS_ITEMS_2" AS
(SELECT i."PRODUCTID" AS PRODUCTID, i."DELIVERYDATE" AS RESULTDATE FROM "_SYS_FINAL_PRODUCTS_2" AS p INNER JOIN "Item_A" AS i ON p.pr
oductid = i."PRODUCTID" WHERE i.DELIVERYDATE >=__typed_Daydate__($1) AND i.DELIVERYDATE <= __typed_Daydate__($2)),
"_SYS_AGGREGATED_ITEMS_2" AS
(SELECT PRODUCTID, RESULTDATE, COUNT(PRODUCTID) AS NUM_RESULT FROM "_SYS_ITEMS_2" "ITEMS" GROUP BY PRODUCTID, RESULTDATE)
SELECT * FROM "_SYS_AGGREGATED_ITEMS_2" "AGGREGATED_ITEMS" ORDER BY PRODUCTID, RESULTDATE;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 12
INLINE feature
Output of inlining – Same dependency
CREATE PROCEDURE "get_results"(
IN im_category VARCHAR(40), IN im_typecode VARCHAR(2),IN im_start_date DATE DEFAULT '2022-06-02', IN im_end_date DATE DEFAULT '2022-08-31',
OUT RESULTS TABLE (PRODUCTID NVARCHAR(10), RESULTDATE DAYDATE, NUM_RESULT BIGINT)
) AS BEGIN
WITH
"_SYS_FINAL_PRODUCTS_2" AS
(SELECT * FROM "Products_A" WHERE category = CAST(N'Notebooks' AS NVARCHAR(40)) AND typecode = CAST(N'PR' AS NVARCHAR(2)) ),
"_SYS_ITEMS_2" AS
(SELECT i."PRODUCTID" AS PRODUCTID, i."DELIVERYDATE" AS RESULTDATE FROM "_SYS_FINAL_PRODUCTS_2" AS p INNER JOIN "Item_A" AS i ON p.pr
oductid = i."PRODUCTID" WHERE i.DELIVERYDATE >=__typed_Daydate__($1) AND i.DELIVERYDATE <= __typed_Daydate__($2)),
"_SYS_AGGREGATED_ITEMS_2" AS
(SELECT PRODUCTID, RESULTDATE, COUNT(PRODUCTID) AS NUM_RESULT FROM "_SYS_ITEMS_2" "ITEMS" GROUP BY PRODUCTID, RESULTDATE)
SELECT * FROM "_SYS_AGGREGATED_ITEMS_2" "AGGREGATED_ITEMS" ORDER BY PRODUCTID, RESULTDATE;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 13
INLINE feature
SQL hint NO_INLINE for statement #1
Block inlining of SQL statement #1 into others
CREATE PROCEDURE "get_results"(
IN im_category VARCHAR(40), IN im_typecode VARCHAR(2),IN im_start_date DATE DEFAULT '2022-06-02', IN im_end_date DATE DEFAULT '2022-08-31',
OUT RESULTS TABLE (PRODUCTID NVARCHAR(10), RESULTDATE DAYDATE, NUM_RESULT BIGINT)
) AS BEGIN
-- Statement#1
final_products = SELECT * FROM "Products_A" WHERE category = :im_category AND typecode = :im_typecode WITH HINT (NO_INLINE);
-- Statement#2
items = SELECT i."PRODUCTID" AS PRODUCTID, i."DELIVERYDATE" AS RESULTDATE FROM :final_products AS p INNER JOIN "Item_A" AS i ON p.productid =
i."PRODUCTID" WHERE i.DELIVERYDATE >=:im_start_date AND i.DELIVERYDATE <= :im_end_date;
-- Statement#3
aggregated_items = SELECT PRODUCTID, RESULTDATE, COUNT(PRODUCTID) AS NUM_RESULT FROM :items GROUP BY PRODUCTID, RESULTDATE;
-- Statement#4
RESULTS = SELECT * FROM :aggregated_items ORDER BY PRODUCTID, RESULTDATE;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 14
INLINE feature
Example – NO_INLINE for statement #1
Statement #1 is executed separately and others are combined by the inlining feature
CREATE PROCEDURE "get_results"(
IN im_category VARCHAR(40), IN im_typecode VARCHAR(2),IN im_start_date DATE DEFAULT '2022-06-02', IN im_end_date DATE DEFAULT '2022-08-31',
OUT RESULTS TABLE (PRODUCTID NVARCHAR(10), RESULTDATE DAYDATE, NUM_RESULT BIGINT)
) AS BEGIN
-- Statement#1
final_products = SELECT * FROM "Products_A" WHERE category = :im_category AND typecode = :im_typecode WITH HINT (NO_INLINE);
-- Statement#2
items = SELECT i."PRODUCTID" AS PRODUCTID, i."DELIVERYDATE" AS RESULTDATE FROM :final_products AS p INNER JOIN "Item_A" AS i ON p.productid =
i."PRODUCTID" WHERE i.DELIVERYDATE >=:im_start_date AND i.DELIVERYDATE <= :im_end_date;
-- Statement#3
aggregated_items = SELECT PRODUCTID, RESULTDATE, COUNT(PRODUCTID) AS NUM_RESULT FROM :items GROUP BY PRODUCTID, RESULTDATE;
-- Statement#4
RESULTS = SELECT * FROM :aggregated_items ORDER BY PRODUCTID, RESULTDATE;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 15
INLINE feature
Output of NO_INLINE hint – Explain plan for CALL
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.
DELETE FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'INLINE';
EXPLAIN PLAN SET STATEMENT_NAME = 'INLINE' FOR
CALL "get_results"(
IM_CATEGORY => 'Notebooks',
IM_TYPECODE => 'PR',
RESULTS => ?);
SELECT * FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'INLINE';
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 16
INLINE feature
Output of NO_INLINE hint – Explain plan for CALL
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.
DELETE FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'INLINE';
EXPLAIN PLAN SET STATEMENT_NAME = 'INLINE' FOR
CALL "get_results"(
IM_CATEGORY => 'Notebooks',
IM_TYPECODE => 'PR',
RESULTS => ?);
SELECT * FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'INLINE';
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 17
INLINE feature
Output of NO_INLINE hint – 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);
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 18
INLINE feature
Output of NO_INLINE hint – 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);
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 19
INLINE feature
Output of NO_INLINE hint – 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);
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 20
INLINE feature
SQL hint NO_INLINE for statement #1, #2, and #3
Block inlininging of all SQL statements
CREATE PROCEDURE "get_results"(
IN im_category VARCHAR(40), IN im_typecode VARCHAR(2),IN im_start_date DATE DEFAULT '2022-06-02', IN im_end_date DATE DEFAULT '2022-08-31',
OUT RESULTS TABLE (PRODUCTID NVARCHAR(10), RESULTDATE DAYDATE, NUM_RESULT BIGINT)
) AS BEGIN
-- Statement#1
final_products = SELECT * FROM "Products_A" WHERE category = :im_category AND typecode = :im_typecode WITH HINT (NO_INLINE);
-- Statement#2
items = SELECT i."PRODUCTID" AS PRODUCTID, i."DELIVERYDATE" AS RESULTDATE FROM :final_products AS p INNER JOIN "Item_A" AS i ON p.productid =
i."PRODUCTID" WHERE i.DELIVERYDATE >=:im_start_date AND i.DELIVERYDATE <= :im_end_date WITH HINT (NO_INLINE);
-- Statement#3
aggregated_items = SELECT PRODUCTID, RESULTDATE, COUNT(PRODUCTID) AS NUM_RESULT FROM :items GROUP BY PRODUCTID, RESULTDATE WITH HINT (NO_INLINE);
-- Statement#4
RESULTS = SELECT * FROM :aggregated_items ORDER BY PRODUCTID, RESULTDATE;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 21
INLINE feature
Output of NO_INLINE hint – Explain plan for CALL
All four statements are executed separately
DELETE FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'INLINE';
EXPLAIN PLAN SET STATEMENT_NAME = 'INLINE' FOR
CALL "get_results"(
IM_CATEGORY => 'Notebooks',
IM_TYPECODE => 'PR',
RESULTS => ?);
SELECT * FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'INLINE';
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 22
INLINE feature
Output of NO_INLINE hint – Plan profiler
All four statements are executed separately
CALL "get_results"(
IM_CATEGORY => 'Notebooks',
IM_TYPECODE => 'PR',
RESULTS => ?) WITH HINT (SQLSCRIPT_PLAN_PROFILER);
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 23
INLINE feature
Output of NO_INLINE hint – Plan profiler
Result sets are materialized and copied to table variables
CALL "get_results"(
IM_CATEGORY => 'Notebooks',
IM_TYPECODE => 'PR',
RESULTS => ?) WITH HINT (SQLSCRIPT_PLAN_PROFILER);
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 24
INLINE feature
SQL hint NO_INLINE of the last SQL statement
What happens if statement #4 has NO_INLINE hint?
CREATE PROCEDURE "get_results"(
IN im_category VARCHAR(40), IN im_typecode VARCHAR(2),IN im_start_date DATE DEFAULT '2022-06-02', IN im_end_date DATE DEFAULT '2022-08-31',
OUT RESULTS TABLE (PRODUCTID NVARCHAR(10), RESULTDATE DAYDATE, NUM_RESULT BIGINT)
) AS BEGIN
-- Statement#1
final_products = SELECT * FROM "Products_A" WHERE category = :im_category AND typecode = :im_typecode WITH HINT (NO_INLINE);
-- Statement#2
items = SELECT i."PRODUCTID" AS PRODUCTID, i."DELIVERYDATE" AS RESULTDATE FROM :final_products AS p INNER JOIN "Item_A" AS i ON p.productid =
i."PRODUCTID" WHERE i.DELIVERYDATE >=:im_start_date AND i.DELIVERYDATE <= :im_end_date WITH HINT (NO_INLINE);
-- Statement#3
aggregated_items = SELECT PRODUCTID, RESULTDATE, COUNT(PRODUCTID) AS NUM_RESULT FROM :items GROUP BY PRODUCTID, RESULTDATE WITH HINT (NO_INLINE);
-- Statement#4
RESULTS = SELECT * FROM :aggregated_items ORDER BY PRODUCTID, RESULTDATE WITH HINT (NO_INLINE);
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 25
INLINE feature
SQL hint NO_INLINE of the last SQL statement
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
Block combination of statement #4 and #5
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 26
INLINE feature
SQL hint NO_INLINE of CALL statement
Procedure flattening is blocked
CREATE OR REPLACE PROCEDURE "get_results_wrapper"()
AS BEGIN
CALL "get_results"(IM_CATEGORY => 'Notebooks', IM_TYPECODE => 'PR', RESULTS => :RESULT_TAB) WITH HINT (NO_INLINE);
-- Statement#5
SELECT * FROM :RESULT_TAB;
END;
CALL "get_results_wrapper"() // Explain plan for CALL
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 27
INLINE feature
SQL hint NO_INLINE and SQLScript optimization rules
Constant
propagation
Control flow Procedure
simplification flattening
SQL statement
inlining &
parallelization
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 28
INLINE feature
Key takeaways
Inlining combines multiple short queries associated
with table variables into a single query.
▪ More benefit from of SQL optimizer
▪ Less materialization of intermediate results
NO_INLINE hint can block statement inlining and
procedure flattening.
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 29
Thank you.
Contact information:
[email protected]
Follow all of SAP
www.sap.com/contactsap
© 2023 SAP SE or an SAP affiliate company. All rights reserved.
No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of
SAP SE or an SAP affiliate company.
The information contained herein may be changed without prior notice. Some software products marketed by SAP SE and its
distributors contain proprietary software components of other software vendors. National product specifications may vary.
These materials are provided by SAP SE or an SAP affiliate company for informational purposes only, without representation or
warranty of any kind, and SAP or its affiliated companies shall not be liable for errors or omissions with respect to the materials.
The only warranties for SAP or SAP affiliate company products and services are those that are set forth in the express warranty
statements accompanying such products and services, if any. Nothing herein should be construed as constituting an additional
warranty.
In particular, SAP SE or its affiliated companies have no obligation to pursue any course of business outlined in this document or
any related presentation, or to develop or release any functionality mentioned therein. This document, or any related presentation,
and SAP SE’s or its affiliated companies’ strategy and possible future developments, products, and/or platforms, directions, and
functionality are all subject to change and may be changed by SAP SE or its affiliated companies at any time for any reason
without notice. The information in this document is not a commitment, promise, or legal obligation to deliver any material, code, or
functionality. All forward-looking statements are subject to various risks and uncertainties that could cause actual results to differ
materially from expectations. Readers are cautioned not to place undue reliance on these forward-looking statements, and they
should not be relied upon in making purchasing decisions.
SAP and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered
trademarks of SAP SE (or an SAP affiliate company) in Germany and other countries. All other product and service names
mentioned are the trademarks of their respective companies.
See www.sap.com/trademark for additional trademark information and notices.
Week 3: Investigating SQLScript Performance Caused by SQL
Unit 2: Case Study 1 – Using the INLINE Feature
Case study 1 – Using the INLINE feature
Symptom
A SQLScript procedure runs for about 18 seconds,
which is much longer than expected.
The CALL statement looks like this:
call "SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS3"('717');
▪ The input parameter is given as a constant value, but it
keeps changing.
▪ When it is executed with same input value, it runs quickly.
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 2
Case study 1 – Using the INLINE feature
Check OVERVIEW
A SQLScript procedure runs for about 18 seconds,
which is much longer than expected.
The CALL statement looks like this:
call "SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS3"('717');
▪ The input parameter is given as a constant value, but it
keeps changing.
▪ When it is executed with same input value, it runs quickly.
"SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELE
So, collect the “Plan Visualizer trace” for this CALL
statement with a different input value.
Here’s the OVERVIEW page of the SQL analyzer.
▪ Compilation: 218.255 ms / Execution: 17.988 s
▪ Top dominant plan operator
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 3
Case study 1 – Using the INLINE feature
Check PLAN GRAPH
“Inclusive time” of the most dominant
operator is 17.977s, whereas the next
operator has only 3.519s.
/* procedure: "SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS2" variable: …
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 4
Case study 1 – Using the INLINE feature
Check STATEMENT_STATISTICS
CALL statement itself
▪ Execution time: 17,983.037 ms
▪ Compilation time: 218.224 ms
This inner SQL statement call "SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEM
▪ Execution time: 423.508 ms
▪ Compilation time: 13,907.535 ms
select * from "CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 5
Case study 1 – Using the INLINE feature
Check STATEMENT_STATISTICS
CALL statement itself
▪ Execution time: 17,983.037 ms
▪ Compilation time: 218.224 ms
This inner SQL statement call "SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEM
▪ Execution time: 423.508 ms
▪ Compilation time: 13,907.535 ms
select * from "CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS
Compilation time of CALL statement includes only SQLScript compilation/optimization time.
Execution time of CALL statement includes compilation/execution time of inner SQL statements.
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 6
Case study 1 – Using the INLINE feature
Check TIMELINE
TIMELINE also shows the compilation time of the problematic inner SQL statement is dominant.
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 7
Case study 1 – Using the INLINE feature
Open inner plan
4.057 s
Click “open” in the Deep Dive field to open the
inner plan.
COMPILATION SUMMARY of inner plan shows
“rewriting time” is 10 seconds.
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 8
Case study 1 – Using the INLINE feature
Check the comment of the SQL statement in STATEMENT STATISTICS
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
/* procedure: "SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS2" variable: ET_MDPS "SAPHDB"."CL_ABC_READ
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 9
Case study 1 – Using the INLINE feature
Check the comment of the SQL statement in PLAN GRAPH
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:
/* procedure: "SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS2" variable: ET_MDPS …
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 10
Case study 1 – Using the INLINE feature
NO_INLINE hint
According to the comment of the problematic
query, it is the output of the inlining optimization,
merging 17 inner SQL statements. procedure: "SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS2"
variable: LT_RESB line: 21 col: 9 (at pos 1078)
It takes about 14 seconds to compile this very
complex query. 1
2
CREATE procedure
"CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS2"
3 (
4 in "IV_MANDT" NVARCHAR (000003),
To reduce the complexity, add a NO_INLINE 5 in "IT_SEL" "CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS=>P00000#ttyp",
6 out "ET_MDPS" "CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS=>P00001#ttyp"
hint at the end of the 17 inner statements where 7 )
the comment points. 8 language sqlscript sql security invoker reads sql data as begin
... ...
21 lt_resb = select
22 matnr, werks, berid, dat00, delkz, plumi, abs(mng01) as mng01
... ...
44 and not ( resb_flex.delkz = 'BB' and resb_flex.delvr =
45 WITH HINT (NO_INLINE);
... ...
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 11
Case study 1 – Using the INLINE feature
Check the new result – OVERVIEW
The execution time is reduced from 17.988 s to 2.358 s.
"SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MR
"SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEME
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 12
Case study 1 – Using the INLINE feature
Check the new result – STATEMENT STATISTICS
More inner SQL statements are executed than
before.
call "SAPHDB"."CL_ABC_READ_DEF_BASIC=>
call "SAPHDB"."CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEM
select * from "CL_ABC_READ_DEF_BASIC=>GET_MRP_ELEMENTS
select * from "CL_ABC_READ_DEF_BASIC=>GET_
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 13
Case study 1 – Using the INLINE feature
Check the new result
More inner SQL statements are executed than
before.
call "SAPHDB"."CL_ABC_READ_DEF_BASIC=>
Total compilation time of newly executed 16
statements is about 16 seconds, which is longer
than 14 seconds before.
How can this procedure run faster now
(2.358 secs) than before(17.358 secs)?
select * from "CL_ABC_READ_DEF_BASIC=>GET_
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 14
Case study 1 – Using the INLINE feature
Check the new result – TIMELINE
16 SQL statements are compiled
in parallel.
This consumes more CPU
resources, but reduces the
response time a lot.
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 15
Case study 1 – Using the INLINE feature
Check the new result – PLAN GRAPH
Plan Graph shows parallel execution of 16 inner SQL statements.
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 16
Case study 1 – Using the INLINE feature
Key takeaways
Understand the output of SQLScript optimization first,
then use NO_INLINE properly, only when the output
causes an issue.
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 17
Thank you.
Contact information:
[email protected]
Follow all of SAP
www.sap.com/contactsap
© 2023 SAP SE or an SAP affiliate company. All rights reserved.
No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of
SAP SE or an SAP affiliate company.
The information contained herein may be changed without prior notice. Some software products marketed by SAP SE and its
distributors contain proprietary software components of other software vendors. National product specifications may vary.
These materials are provided by SAP SE or an SAP affiliate company for informational purposes only, without representation or
warranty of any kind, and SAP or its affiliated companies shall not be liable for errors or omissions with respect to the materials.
The only warranties for SAP or SAP affiliate company products and services are those that are set forth in the express warranty
statements accompanying such products and services, if any. Nothing herein should be construed as constituting an additional
warranty.
In particular, SAP SE or its affiliated companies have no obligation to pursue any course of business outlined in this document or
any related presentation, or to develop or release any functionality mentioned therein. This document, or any related presentation,
and SAP SE’s or its affiliated companies’ strategy and possible future developments, products, and/or platforms, directions, and
functionality are all subject to change and may be changed by SAP SE or its affiliated companies at any time for any reason
without notice. The information in this document is not a commitment, promise, or legal obligation to deliver any material, code, or
functionality. All forward-looking statements are subject to various risks and uncertainties that could cause actual results to differ
materially from expectations. Readers are cautioned not to place undue reliance on these forward-looking statements, and they
should not be relied upon in making purchasing decisions.
SAP and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered
trademarks of SAP SE (or an SAP affiliate company) in Germany and other countries. All other product and service names
mentioned are the trademarks of their respective companies.
See www.sap.com/trademark for additional trademark information and notices.
Week 3: Investigating SQLScript Performance Caused by SQL
Unit 3: BIND_AS_PARAMETER and
BIND_AS_VALUE Functions
BIND_AS_PARAMETER and BIND_AS_VALUE functions
Introduction
Constant
propagation
Control flow Procedure
simplification flattening
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
SQLScript functions to control
parameterization behavior of scalar variables
explicitly.
BIND_AS_PARAMETER treats a scalar
variable as a query parameter.
BIND_AS_VALUE treats a scalar variable as
a constant value.
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 3
BIND_AS_PARAMETER and BIND_AS_VALUE functions
Example – Procedure “get_results”
Parameter im_category and im_typecode
CREATE PROCEDURE "get_results"(
IN im_category NVARCHAR(40), IN im_typecode NVARCHAR(2),IN im_start_date DATE DEFAULT '2022-06-02', IN im_end_date DATE DEFAULT '2022-08-31',
OUT RESULTS TABLE (PRODUCTID NVARCHAR(10), RESULTDATE DAYDATE, NUM_RESULT BIGINT)
) AS BEGIN
-- Statement#1
final_products = SELECT * FROM "Products_A" WHERE category = :im_category AND typecode = :im_typecode with hint(NO_INLINE);
-- Statement#2
items = SELECT i."PRODUCTID" AS PRODUCTID, i."DELIVERYDATE" AS RESULTDATE FROM :final_products AS p INNER JOIN "Item_A" AS i ON p.productid =
i."PRODUCTID" WHERE i.DELIVERYDATE >=:im_start_date AND i.DELIVERYDATE <= :im_end_date with hint(NO_INLINE);
-- Statement#3
aggregated_items = SELECT PRODUCTID, RESULTDATE, COUNT(PRODUCTID) AS NUM_RESULT FROM :items GROUP BY PRODUCTID, RESULTDATE;
-- Statement#4
RESULTS = SELECT * FROM :aggregated_items ORDER BY PRODUCTID, RESULTDATE;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 4
BIND_AS_PARAMETER and BIND_AS_VALUE functions
CALL get_results with constant values
When using constant values, check Explain Plan for CALL.
DELETE FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
EXPLAIN PLAN SET STATEMENT_NAME = 'BIND_TEST' FOR
CALL "get_results"(
SQL statement in the code
IM_CATEGORY => 'Notebooks',
SELECT * FROM "Products_A" WHERE category = :im_category AND typecode = :im_typecode …
IM_TYPECODE => 'PR',
RESULTS => ?);
SELECT * FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 5
BIND_AS_PARAMETER and BIND_AS_VALUE functions
CALL get_results with constant values
When using constant values, check Explain Plan for CALL.
DELETE FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
EXPLAIN PLAN SET STATEMENT_NAME = 'BIND_TEST' FOR
CALL "get_results"(
SQL statement in the code
IM_CATEGORY => 'Notebooks',
SELECT * FROM "Products_A" WHERE category = :im_category AND typecode = :im_typecode …
IM_TYPECODE => 'PR',
RESULTS => ?);
SELECT * FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 6
BIND_AS_PARAMETER and BIND_AS_VALUE functions
CALL get_results with parameter values
When using parameter values, check Explain Plan for CALL.
DELETE FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
EXPLAIN PLAN SET STATEMENT_NAME = 'BIND_TEST' FOR
CALL "get_results"(
SQL statement in the code
IM_CATEGORY => ? , -- 'Notebooks'
SELECT * FROM "Products_A" WHERE category = :im_category AND typecode = :im_typecode …
IM_TYPECODE => ? , -- 'PR'
RESULTS => ?);
SELECT * FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 7
BIND_AS_PARAMETER and BIND_AS_VALUE functions
CALL get_results with parameter values
When using parameter values, check Explain Plan for CALL.
DELETE FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
EXPLAIN PLAN SET STATEMENT_NAME = 'BIND_TEST' FOR
CALL "get_results"(
SQL statement in the code
IM_CATEGORY => ? , -- 'Notebooks'
SELECT * FROM "Products_A" WHERE category = :im_category AND typecode = :im_typecode …
IM_TYPECODE => ? , -- 'PR'
RESULTS => ?);
SELECT * FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 8
BIND_AS_PARAMETER and BIND_AS_VALUE functions
Literal query vs. parameterized query
CALL "get_results"(IM_CATEGORY => 'Notebooks', …) CALL "get_results"(IM_CATEGORY => ?, …)
SELECT * FROM "Products_A" WHERE category = SELECT * FROM "Products_A" WHERE category =
CAST(N'Notebooks' AS NVARCHAR(40)) AND vs. __typed_NString__($1, 40) AND typecode =
typecode = CAST(N'PR' AS NVARCHAR(2)); __typed_NString__($2, 2);
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.
Literal query vs. Parameterized query
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 9
BIND_AS_PARAMETER and BIND_AS_VALUE functions
Literal query vs. parameterized query
CALL "get_results"(IM_CATEGORY => 'Notebooks', …) CALL "get_results"(IM_CATEGORY => ?, …)
SELECT * FROM "Products_A" WHERE category = SELECT * FROM "Products_A" WHERE category =
CAST(N'Notebooks' AS NVARCHAR(40)) AND vs. __typed_NString__($1, 40) AND typecode =
typecode = CAST(N'PR' AS NVARCHAR(2)); __typed_NString__($2, 2);
Literal query vs. Parameterized query
Literal query
▪ Whenever values are changed, a new query plan is generated. Therefore, it takes more resources
(cpu/memory) for query compilation and the plan cache pool.
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
With BIND_AS_PARAMETER and BIND_AS_VALUE
CREATE PROCEDURE "get_results"(
IN im_category VARCHAR(40), IN im_typecode VARCHAR(2),IN im_start_date DATE DEFAULT '2022-06-02', IN im_end_date DATE DEFAULT '2022-08-31',
OUT RESULTS TABLE (PRODUCTID NVARCHAR(10), RESULTDATE DAYDATE, NUM_RESULT BIGINT)
) AS BEGIN
-- Statement#1
final_products = SELECT * FROM "Products_A" WHERE category = BIND_AS_PARAMETER(:im_category) AND typecode = BIND_AS_VALUE(:im_typecode) with
hint(NO_INLINE);
-- Statement#2
items = SELECT i."PRODUCTID" AS PRODUCTID, i."DELIVERYDATE" AS RESULTDATE FROM :final_products AS p INNER JOIN "Item_A" AS i ON p.productid =
i."PRODUCTID" WHERE i.DELIVERYDATE >=:im_start_date AND i.DELIVERYDATE <= :im_end_date with hint(NO_INLINE);
-- Statement#3
aggregated_items = SELECT PRODUCTID, RESULTDATE, COUNT(PRODUCTID) AS NUM_RESULT FROM :items GROUP BY PRODUCTID, RESULTDATE;
-- Statement#4
RESULTS = SELECT * FROM :aggregated_items ORDER BY PRODUCTID, RESULTDATE;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 11
BIND_AS_PARAMETER and BIND_AS_VALUE functions
CALL get_results with constant values
When using constant values, check Explain Plan for CALL.
DELETE FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
EXPLAIN PLAN SET STATEMENT_NAME = 'BIND_TEST' FOR
CALL "get_results"(
SQL statement in the code
IM_CATEGORY => 'Notebooks',
SELECT * FROM "Products_A" WHERE
IM_TYPECODE => 'PR',
category = BIND_AS_PARAMETER(:im_category) AND typecode = BIND_AS_VALUE(:im_typecode) …
RESULTS => ?);
SELECT * FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 12
BIND_AS_PARAMETER and BIND_AS_VALUE functions
CALL get_results with constant values
When using constant values, check Explain Plan for CALL.
DELETE FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
EXPLAIN PLAN SET STATEMENT_NAME = 'BIND_TEST' FOR
CALL "get_results"(
SQL statement in the code
IM_CATEGORY => 'Notebooks',
SELECT * FROM "Products_A" WHERE
IM_TYPECODE => 'PR',
category = BIND_AS_PARAMETER(:im_category) AND typecode = BIND_AS_VALUE(:im_typecode) …
RESULTS => ?);
SELECT * FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 13
BIND_AS_PARAMETER and BIND_AS_VALUE functions
CALL get_results with parameter values
When using parameter values, check Explain Plan for CALL.
DELETE FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
EXPLAIN PLAN SET STATEMENT_NAME = 'BIND_TEST' FOR
CALL "get_results"(
SQL statement in the code
IM_CATEGORY => ? , -- 'Notebooks'
SELECT * FROM "Products_A" WHERE
IM_TYPECODE => ? , -- 'PR'
category = BIND_AS_PARAMETER(:im_category) AND typecode = BIND_AS_VALUE(:im_typecode) …
RESULTS => ?);
SELECT * FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 14
BIND_AS_PARAMETER and BIND_AS_VALUE functions
CALL get_results with parameter values
When using parameter values, check Explain Plan for CALL.
DELETE FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
EXPLAIN PLAN SET STATEMENT_NAME = 'BIND_TEST' FOR
CALL "get_results"(
SQL statement in the code
IM_CATEGORY => ? , -- 'Notebooks'
SELECT * FROM "Products_A" WHERE
IM_TYPECODE => ? , -- 'PR'
category = BIND_AS_PARAMETER(:im_category) AND typecode = BIND_AS_VALUE(:im_typecode) …
RESULTS => ?);
SELECT * FROM EXPLAIN_CALL_PLANS WHERE STATEMENT_NAME = 'BIND_TEST';
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 15
BIND_AS_PARAMETER and BIND_AS_VALUE functions
Check BIND_AS_VALUE with Plan Profiler
SQL statement in the code
SELECT * FROM "Products_A" WHERE
category = BIND_AS_PARAMETER(:im_category) AND typecode = BIND_AS_VALUE(:im_typecode) …
CALL "get_results"(
IM_CATEGORY => ? , -- 'Notebooks'
IM_TYPECODE => ? , -- 'PR'
RESULTS => ?) WITH HINT (SQLSCRIPT_PLAN_PROFILER);
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 16
BIND_AS_PARAMETER and BIND_AS_VALUE functions
Check BIND_AS_VALUE with Plan Profiler
SQL statement in the code
SELECT * FROM "Products_A" WHERE
category = BIND_AS_PARAMETER(:im_category) AND typecode = BIND_AS_VALUE(:im_typecode) …
CALL "get_results"(
IM_CATEGORY => ? , -- 'Notebooks'
IM_TYPECODE => ? , -- 'PR'
RESULTS => ?) WITH HINT (SQLSCRIPT_PLAN_PROFILER);
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 17
BIND_AS_PARAMETER and BIND_AS_VALUE functions
Key takeaways
BIND_AS_PARAMETER and BIND_AS_VALUE
are SQLScript functions to control the
parameterization behavior of scalar variables
explicitly.
BIND_AS_PARAMETER treats a scalar variable
as a query parameter, so the affected SQL
statement becomes a parameterized query.
BIND_AS_VALUE treats a scalar variable as a
constant value, so the affected SQL statement
becomes a literal query.
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 18
Thank you.
Contact information:
[email protected]
Follow all of SAP
www.sap.com/contactsap
© 2023 SAP SE or an SAP affiliate company. All rights reserved.
No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of
SAP SE or an SAP affiliate company.
The information contained herein may be changed without prior notice. Some software products marketed by SAP SE and its
distributors contain proprietary software components of other software vendors. National product specifications may vary.
These materials are provided by SAP SE or an SAP affiliate company for informational purposes only, without representation or
warranty of any kind, and SAP or its affiliated companies shall not be liable for errors or omissions with respect to the materials.
The only warranties for SAP or SAP affiliate company products and services are those that are set forth in the express warranty
statements accompanying such products and services, if any. Nothing herein should be construed as constituting an additional
warranty.
In particular, SAP SE or its affiliated companies have no obligation to pursue any course of business outlined in this document or
any related presentation, or to develop or release any functionality mentioned therein. This document, or any related presentation,
and SAP SE’s or its affiliated companies’ strategy and possible future developments, products, and/or platforms, directions, and
functionality are all subject to change and may be changed by SAP SE or its affiliated companies at any time for any reason
without notice. The information in this document is not a commitment, promise, or legal obligation to deliver any material, code, or
functionality. All forward-looking statements are subject to various risks and uncertainties that could cause actual results to differ
materially from expectations. Readers are cautioned not to place undue reliance on these forward-looking statements, and they
should not be relied upon in making purchasing decisions.
SAP and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered
trademarks of SAP SE (or an SAP affiliate company) in Germany and other countries. All other product and service names
mentioned are the trademarks of their respective companies.
See www.sap.com/trademark for additional trademark information and notices.
Week 3: Investigating SQLScript Performance Caused by SQL
Unit 4: Case Study 2 – Using BIND_AS_VALUE
Case study 2 – Using BIND_AS_VALUE
Symptom
The application server cancels one of the SQLScript
procedures that runs very long.
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 2
Case study 2 – Using BIND_AS_VALUE
First step
The application server cancels one of the SQLScript
procedures that runs very long.
How can we find out which SQLScript procedure is
problematic?
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 3
Case study 2 – Using BIND_AS_VALUE
First step
The application server cancels one of the SQLScript
procedures that runs very long.
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 ;
// reproduce the issue
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 4
Case study 2 – Using BIND_AS_VALUE
Check the SQL Trace result
Search “cancelled by request” as keywords.
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
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 5
Case study 2 – Using BIND_AS_VALUE
Check the SQL Trace result
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
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 6
Case study 2 – Using BIND_AS_VALUE
Check the SQL Trace result
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
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 7
Case study 2 – Using BIND_AS_VALUE
Second step
The application server cancels one of the SQLScript
procedures that runs very long.
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';
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 8
Case study 2 – Using BIND_AS_VALUE
Check M_ACTIVE_PROCEDURES result
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.
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 9
Case study 2 – Using BIND_AS_VALUE
Investigate the problematic query
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.
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 10
Case study 2 – Using BIND_AS_VALUE
Investigate the problematic query
Try to execute the query with constant values.
/* 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.
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 11
Case study 2 – Using BIND_AS_VALUE
Third step
The application server cancels one of the SQLScript
procedures that runs very long.
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?
Let’s use BIND_AS_VALUE as a solution.
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 12
Case study 2 – Using BIND_AS_VALUE
Apply the BIND_AS_VALUE function
The comment points to where this SQL statement is in “SP_INVENTORY_SNAPSHOT_JANUARY_202301”.
/* 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
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 13
Case study 2 – Using BIND_AS_VALUE
Apply the BIND_AS_VALUE function
In the definition of the procedure, three scalar variables are shown where parameters are.
BI_MY_STORE"."SP_INVENTORY_SNAPSHOT_JANUARY_202301" line: 95
insert into "DSLOCAL"."ZTB_INVENTORY"
select
"MANDT",
...
:current_fisical_week as fiscal_week,
...
from "_SYS_BIC"."BI_MY_STORE.Inventory/CV_SUPPLY"
( placeholder."$$P_LastArunDate$$" => :last_arun_date , placeholder."$$P_LastPreviewDate$$" => :last_preview_date )
where
LENGTH(WERKS) = 4
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 14
Case study 2 – Using BIND_AS_VALUE
Apply the BIND_AS_VALUE function
Apply BIND_AS_VALUE to execute this query as a literal one.
BI_MY_STORE"."SP_INVENTORY_SNAPSHOT_JANUARY_202301" line: 95
insert into "DSLOCAL"."ZTB_INVENTORY"
select
"MANDT",
...
BIND_AS_VALUE(:current_fisical_week) as fiscal_week,
...
from "_SYS_BIC"."BI_MY_STORE.Inventory/CV_SUPPLY"
( placeholder."$$P_LastArunDate$$" => BIND_AS_VALUE(:last_arun_date), placeholder."$$P_LastPreviewDate$$" => BIND_AS_VALUE(:last_preview_date)
)
where
LENGTH(WERKS) = 4
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 15
Case study 2 – Using BIND_AS_VALUE
Key takeaways
SQL Trace shows information about the executed
inner SQL statements during execution of the
SQLScript procedure, once the parameter ‘internal’
= ‘true’ in the [sqltrace] section is configured.
M_ACTIVE_PROCEDURES shows information
about all executed inner SQL statements of an
actively running procedure on the fly.
Comment in actual running SQL statement shows
the position of its definition code.
Depending on the characteristics of a query, you can
change it from a parameterized query to a literal one
or vice versa by using the BIND_AS_VALUE or
BIND_AS_PARAMETER function.
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 16
Thank you.
Contact information:
[email protected]
Follow all of SAP
www.sap.com/contactsap
© 2022 SAP SE or an SAP affiliate company. All rights reserved.
No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of
SAP SE or an SAP affiliate company.
The information contained herein may be changed without prior notice. Some software products marketed by SAP SE and its
distributors contain proprietary software components of other software vendors. National product specifications may vary.
These materials are provided by SAP SE or an SAP affiliate company for informational purposes only, without representation or
warranty of any kind, and SAP or its affiliated companies shall not be liable for errors or omissions with respect to the materials.
The only warranties for SAP or SAP affiliate company products and services are those that are set forth in the express warranty
statements accompanying such products and services, if any. Nothing herein should be construed as constituting an additional
warranty.
In particular, SAP SE or its affiliated companies have no obligation to pursue any course of business outlined in this document or
any related presentation, or to develop or release any functionality mentioned therein. This document, or any related presentation,
and SAP SE’s or its affiliated companies’ strategy and possible future developments, products, and/or platforms, directions, and
functionality are all subject to change and may be changed by SAP SE or its affiliated companies at any time for any reason
without notice. The information in this document is not a commitment, promise, or legal obligation to deliver any material, code, or
functionality. All forward-looking statements are subject to various risks and uncertainties that could cause actual results to differ
materially from expectations. Readers are cautioned not to place undue reliance on these forward-looking statements, and they
should not be relied upon in making purchasing decisions.
SAP and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered
trademarks of SAP SE (or an SAP affiliate company) in Germany and other countries. All other product and service names
mentioned are the trademarks of their respective companies.
See www.sap.com/trademark for additional trademark information and notices.
Week 3: Investigating SQLScript Performance Caused by SQL
Unit 5: Using SQL Hint in SQLScript
Using SQL hint in SQLScript
Introduction
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
How to apply SQL hints
▪ Modify SQLScript code
▪ Add hint using pinning hint or statement hint feature
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 2
Using SQL hint in SQLScript
Procedure HINT_TEST
CREATE PROCEDURE HINT_TEST() CALL HINT_TEST(); // Explain Plan for CALL
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 3
Using SQL hint in SQLScript
Modifying SQLScript code
CREATE PROCEDURE HINT_TEST() CALL HINT_TEST(); // Explain Plan for CALL
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1
WITH HINT (USE_HEX_PLAN);
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 4
Using SQL hint in SQLScript
Modifying SQLScript code
CREATE PROCEDURE HINT_TEST() CALL HINT_TEST(); // Explain Plan for CALL
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1
WITH HINT (USE_HEX_PLAN);
END;
SQL hint is added at the end of the combined SQL statements
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 5
Using SQL hint in SQLScript
Modifying SQLScript code
CREATE PROCEDURE HINT_TEST() CALL HINT_TEST(); // Explain Plan for CALL
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1
WITH HINT (USE_HEX_PLAN);
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 6
Using SQL hint in SQLScript
Modifying SQLScript code
CREATE PROCEDURE HINT_TEST() CALL HINT_TEST(); // Explain Plan for CALL
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1
WITH HINT (USE_HEX_PLAN);
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 7
Using SQL hint in SQLScript
Modifying SQLScript code
CREATE PROCEDURE HINT_TEST() CALL HINT_TEST(); // Explain Plan for CALL
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1
WITH HINT (USE_HEX_PLAN);
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END;
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
CREATE PROCEDURE HINT_TEST() CALL HINT_TEST() WITH HINT (USE_HEX_PLAN);
AS BEGIN // Explain Plan for CALL
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 9
Using SQL hint in SQLScript
HINT from CALL statement
CREATE PROCEDURE HINT_TEST() CALL HINT_TEST() WITH HINT (USE_HEX_PLAN);
AS BEGIN // Explain Plan for CALL
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END;
HINT from CALL statement is not propagated to inner SQL statements
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 10
Using SQL hint in SQLScript
CASCADE
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
Cloud QRC 4/2022
CREATE PROCEDURE HINT_TEST()
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1
WITH HINT (NO_INLINE);
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1
;
END;
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 11
Using SQL hint in SQLScript
CASCADE
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
Cloud QRC 4/2022
CREATE PROCEDURE HINT_TEST()
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1
WITH HINT (NO_INLINE);
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1
;
END;
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
Modify SQLScript code to apply SQL hint.
Explain Plan for CALL is an easy way to show
applied SQL hints.
Inlining optimization stops at a statement with a
SQL hint.
CASCADE allows propagation of SQL hint into
all inner SQL statements.
© 2023 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 13
Thank you.
Contact information:
[email protected]
Follow all of SAP
www.sap.com/contactsap
© 2023 SAP SE or an SAP affiliate company. All rights reserved.
No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of
SAP SE or an SAP affiliate company.
The information contained herein may be changed without prior notice. Some software products marketed by SAP SE and its
distributors contain proprietary software components of other software vendors. National product specifications may vary.
These materials are provided by SAP SE or an SAP affiliate company for informational purposes only, without representation or
warranty of any kind, and SAP or its affiliated companies shall not be liable for errors or omissions with respect to the materials.
The only warranties for SAP or SAP affiliate company products and services are those that are set forth in the express warranty
statements accompanying such products and services, if any. Nothing herein should be construed as constituting an additional
warranty.
In particular, SAP SE or its affiliated companies have no obligation to pursue any course of business outlined in this document or
any related presentation, or to develop or release any functionality mentioned therein. This document, or any related presentation,
and SAP SE’s or its affiliated companies’ strategy and possible future developments, products, and/or platforms, directions, and
functionality are all subject to change and may be changed by SAP SE or its affiliated companies at any time for any reason
without notice. The information in this document is not a commitment, promise, or legal obligation to deliver any material, code, or
functionality. All forward-looking statements are subject to various risks and uncertainties that could cause actual results to differ
materially from expectations. Readers are cautioned not to place undue reliance on these forward-looking statements, and they
should not be relied upon in making purchasing decisions.
SAP and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered
trademarks of SAP SE (or an SAP affiliate company) in Germany and other countries. All other product and service names
mentioned are the trademarks of their respective companies.
See www.sap.com/trademark for additional trademark information and notices.
Week 3: Investigating SQLScript Performance Caused by SQL
Unit 6: Pinning SQL Hint for SQLScript
Pinning SQL hint for SQLScript
Introduction
How to apply SQL hints
▪ Modify SQLScript code
▪ Add hint using pinning hint or statement hint feature
If it is impossible to modify SQLScript code
directly, the following options are available
▪ ALTER SYSTEM {ADD | ALTER | REMOVE}
STATEMENT HINT statement
▪ ALTER SYSTEM {PIN | UNPIN} SQL PLAN
CACHE ENTRY statement
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 2
Pinning SQL hint for SQLScript
Procedure HINT_TEST
CREATE PROCEDURE HINT_TEST()
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END; Check the actual SQL statement executed in
the SQL engine and its STATEMENT_HASH
CALL HINT_TEST() WITH HINT(SQLSCRIPT_PLAN_PROFILER); (available since SAP HANA Cloud QRC 4/2022)
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 3
Pinning SQL hint for SQLScript
Adding statement hints
CREATE PROCEDURE HINT_TEST()
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END; Check the actual SQL statement executed in
the SQL engine and its STATEMENT_HASH
CALL HINT_TEST() WITH HINT(SQLSCRIPT_PLAN_PROFILER); (available since SAP HANA Cloud QRC 4/2022)
ALTER SYSTEM ADD STATEMENT HINT (USE_HEX_PLAN) FOR STATEMENT HASH
'54f3a26840fd0eedc15f6c074cf26ada';
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 4
Pinning SQL hint for SQLScript
Adding statement hints
CREATE PROCEDURE HINT_TEST()
If the result of the Plan Profiler doesn’t show
AS BEGIN
STATEMENT_HASH, find it in
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
M_SQL_PLAN_CACHE
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END;
CALL HINT_TEST() WITH HINT(SQLSCRIPT_PLAN_PROFILER);
SELECT STATEMENT_HASH FROM M_SQL_PLAN_CACHE WHERE STATEMENT_
STRING LIKE '/* procedure: "DBADMIN"."HINT_TEST" line: 5 col: 5
(at pos 172)%’
ALTER SYSTEM ADD STATEMENT HINT (USE_HEX_PLAN) FOR STATEMENT HASH
'54f3a26840fd0eedc15f6c074cf26ada';
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 5
Pinning SQL hint for SQLScript
Adding statement hints
ALTER SYSTEM ALTER CONFIGURATION ('indexserver.ini','DATABASE') SET
('sqltrace', 'trace') = 'on',
('sqltrace', 'user') = 'DBADMIN',
('sqltrace', 'internal') = 'true',
('sqltrace', 'query_plan_trace') = 'on'
WITH RECONFIGURE ;
CALL HINT_TEST();
ALTER SYSTEM ALTER CONFIGURATION ('indexserver.ini','DATABASE') UNSET
('sqltrace', 'trace'),
('sqltrace', 'user'),
('sqltrace', 'internal'),
('sqltrace', 'query_plan_trace')
WITH RECONFIGURE;
SQL HINT is added
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 6
Pinning SQL hint for SQLScript
Pinning hints
CREATE PROCEDURE HINT_TEST()
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY;
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END; Check the actual SQL statement executed in
the SQL engine and its STATEMENT_HASH
CALL HINT_TEST() WITH HINT(SQLSCRIPT_PLAN_PROFILER); (available since SAP HANA Cloud QRC 4/2022)
SELECT PLAN_ID FROM M_SQL_PLAN_CACHE WHERE
STATEMENT_HASH = '54f3a26840fd0eedc15f6c074cf26ada’;
ALTER SYSTEM PIN SQL PLAN CACHE ENTRY 12360002
WITH HINT (USE_HEX_PLAN);
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 7
Pinning SQL hint for SQLScript
GUID in name of table parameter/variable
CREATE PROCEDURE HINT_TEST()
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY
WITH HINT (NO_INLINE);
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END;
CALL HINT_TEST() WITH HINT(SQLSCRIPT_PLAN_PROFILER);
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 8
Pinning SQL hint for SQLScript
GUID in name of table parameter/variable
CREATE PROCEDURE HINT_TEST()
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY
WITH HINT (NO_INLINE);
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END;
CALL HINT_TEST() WITH HINT(SQLSCRIPT_PLAN_PROFILER);
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 9
Pinning SQL hint for SQLScript
GUID in name of table parameter/variable
CREATE PROCEDURE HINT_TEST()
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY The GUID is used for the name of a local
WITH HINT (NO_INLINE); temp table for a persisted table variable.
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END;
CALL HINT_TEST() WITH HINT(SQLSCRIPT_PLAN_PROFILER);
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 10
Pinning SQL hint for SQLScript
GUID in name of table parameter/variable
CREATE PROCEDURE HINT_TEST()
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY The GUID is used for the name of a local
WITH HINT (NO_INLINE); temp table for a persisted table variable.
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
A different GUID value is generated
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1;
END;
when the SQLScript procedure is
compiled again.
CALL HINT_TEST() WITH HINT(SQLSCRIPT_PLAN_PROFILER);
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 11
Pinning SQL hint for SQLScript
GUID in name of table parameter/variable
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.
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 12
Pinning SQL hint for SQLScript
Pinning hints
CREATE PROCEDURE HINT_TEST()
AS BEGIN
RESULT1 = SELECT DUMMY COL1, DUMMY || '123' COL2 FROM DUMMY
WITH HINT (NO_INLINE);
RESULT2 = SELECT COL1, COL2 || '456' COL2 FROM :RESULT1;
SELECT * FROM DUMMY T1, :RESULT2 T2 WHERE T1.DUMMY = T2.COL1; Check the actual SQL statement executed in
END; the SQL engine and its STATEMENT_HASH
(available since SAP HANA Cloud QRC 4/2022)
CALL HINT_TEST(); // Execute once
SELECT PLAN_ID FROM M_SQL_PLAN_CACHE WHERE
STATEMENT_HASH LIKE '%HINT_TEST%’;
ALTER SYSTEM PIN SQL PLAN CACHE ENTRY 14700002
WITH HINT (USE_HEX_PLAN);
ALTER SYSTEM PIN SQL PLAN CACHE ENTRY 14680002;
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 13
Pinning SQL hint for SQLScript
Key takeaways
Adding/pinning statement hints can be a solution
when modifying SQLScript code isn’t allowed.
Hint should be applied on actual executed SQL
statements. Use STATEMENT_HASH and/or
PLAN ID.
The names of table parameters/variables have a
GUID which changes whenever a SQLScript
procedure is compiled. In this case, pinning the
CALL statement as well as inner SQL statements
can be a solution.
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 14
Pinning SQL hint for SQLScript
Closing
Using the Optimizer for SQLScript Programming in SAP HANA
Week 1
Understanding SAP HANA SQLScript Optimizer
Week 2
SAP HANA SQLScript Supportability Features
Week 3
Investigating SQLScript Performance Caused by SQL
Final Exam
© 2022 SAP SE or an SAP affiliate company. All rights reserved. ǀ PUBLIC 15
Thank you.
Contact information:
[email protected]
Follow all of SAP
www.sap.com/contactsap
© 2022 SAP SE or an SAP affiliate company. All rights reserved.
No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of
SAP SE or an SAP affiliate company.
The information contained herein may be changed without prior notice. Some software products marketed by SAP SE and its
distributors contain proprietary software components of other software vendors. National product specifications may vary.
These materials are provided by SAP SE or an SAP affiliate company for informational purposes only, without representation or
warranty of any kind, and SAP or its affiliated companies shall not be liable for errors or omissions with respect to the materials.
The only warranties for SAP or SAP affiliate company products and services are those that are set forth in the express warranty
statements accompanying such products and services, if any. Nothing herein should be construed as constituting an additional
warranty.
In particular, SAP SE or its affiliated companies have no obligation to pursue any course of business outlined in this document or
any related presentation, or to develop or release any functionality mentioned therein. This document, or any related presentation,
and SAP SE’s or its affiliated companies’ strategy and possible future developments, products, and/or platforms, directions, and
functionality are all subject to change and may be changed by SAP SE or its affiliated companies at any time for any reason
without notice. The information in this document is not a commitment, promise, or legal obligation to deliver any material, code, or
functionality. All forward-looking statements are subject to various risks and uncertainties that could cause actual results to differ
materially from expectations. Readers are cautioned not to place undue reliance on these forward-looking statements, and they
should not be relied upon in making purchasing decisions.
SAP and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered
trademarks of SAP SE (or an SAP affiliate company) in Germany and other countries. All other product and service names
mentioned are the trademarks of their respective companies.
See www.sap.com/trademark for additional trademark information and notices.