openSAP Hanasql2 Week 3 All Slides

Download as pdf or txt
Download as pdf or txt
You are on page 1of 120

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:

open@sap.com
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:

open@sap.com
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:

open@sap.com
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:

open@sap.com
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:

open@sap.com
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:

open@sap.com
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.

You might also like