Vous êtes sur la page 1sur 5

How To Use SQL Profiles for Queries Using Different Literals [ID 1253696.

1]

-------------------------------------------------------------------------------Modified:Oct 26, 2010Type:HOWTOStatus:MODERATEDPriority:3


Bottom

Comments (0) To

In this Document
Goal
Solution

-------------------------------------------------------------------------------This document is being delivered to you via Oracle Support's Rapid Visibility (R
aV) process and therefore has not been subject to an independent technical revie
w.

Applies to:
Oracle Server - Enterprise Edition - Version: 10.2.0.1 to 11.2.0.1.0 - Release:
10.2 to 11.2
Information in this document applies to any platform.
Goal
1. To create SQL Profiles for the queries using literals where in the different
literal values are passed for every execution.
2. To make the SQL Profile used for SQL with the changing literal values in ever
y execution.
Default behaviour: By default, if SQL Profile is created for the sql with litera
ls, then the profile would be used only for the SQL with whatever literals used
while running the tuning advisor. For the same sql with only change in literals,
the profile would not be used.
Solution
Showing default behaviour of SQL Profile.
Example:
SQL> create table test (n number );
Table created.
declare
begin
for i in 1 .. 10000
loop
insert into test values(i);

commit;
end loop;
end;
PL/SQL procedure successfully completed.
create index test_idx on test(n);
Index created.
analyze table test estimate statistics (OR use dbms_stats)
Table analyzed.
select /*+ no_index(test test_idx) */ * from test where n=1
Execution Plan
---------------------------------------------------------0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=6 Card=1 Bytes=13)
1 0 TABLE ACCESS (FULL) OF 'TEST' (TABLE) (Cost=6 Card=1 Bytes
=13)
Let us just use SQL Tuning Advisor for the following sql to get recommendations
out of it.
select /*+ no_index(test test_idx) */ * from test where n=1;
SQL> DECLARE
2 my_task_name VARCHAR2(30);
3 my_sqltext CLOB;
4 BEGIN
5 my_sqltext := 'select /*+ no_index(test test_idx) */ * from test where n=1';
6 my_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
7 sql_text=> my_sqltext,
8 user_name => 'SCOTT',
9 scope => 'COMPREHENSIVE',
10 time_limit => 60,
11 task_name => 'my_sql_tuning_task_2',
12 description => 'Task to tune a query on a specified table');
13 END;
14 /
PL/SQL procedure successfully completed.
SQL> exec DBMS_SQLTUNE.EXECUTE_TUNING_TASK( task_name => 'my_sql_tuning_task_2')
;
PL/SQL procedure successfully completed.
SQL> set long 2000
SQL> SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK( 'my_sql_tuning_task_2') from DUAL;
FINDINGS SECTION (1 finding)
-------------------------------------------------------------------------------

1- SQL Profile Finding (see explain plans section below)


-------------------------------------------------------DBMS_SQLTUNE.REPORT_TUNING_TASK('MY_SQL_TUNING_TASK_2')
-------------------------------------------------------------------------------A potentially better execution plan was found for this statement.
Recommendation (estimated benefit: 84.03%)
------------------------------------------ Consider accepting the recommended SQL profile.
execute dbms_sqltune.accept_sql_profile(task_name =>
'my_sql_tuning_task_2', replace => TRUE);
Now the SQL is created for the above sql.
SQL> execute dbms_sqltune.accept_sql_profile(task_name =>'my_sql_tuning_task_2',
replace => TRUE);
PL/SQL procedure successfully completed.

If we execute the sql it uses the SQL Profile only for particular literals which
are passed during the creation.
SQL> select /*+ no_index(test test_idx) */ * from test where n=1;
N
---------1
Execution Plan
---------------------------------------------------------Plan hash value: 2882402178
----------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 3 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| TEST_IDX | 1 | 3 | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------1 - access("N"=1)
Note
----- SQL profile "SYS_SQLPROF_014af9c017890000" used for this statement
But if we change the literal to another, the the profile would not be used and o
ptimizer uses different plan.
SQL> select /*+ no_index(test test_idx) */ * from test where n=2;
N
---------2

Execution Plan
---------------------------------------------------------Plan hash value: 1357081020
-------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 3 | 6 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| TEST | 1 | 3 | 6 (0)| 00:00:01 |
-------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------1 - filter("N"=2) => SQL profile not used with different literal
To maintain plan stability and make use of the SQL profile to be used for whatev
er literals passed, there is one option called FORCE_MATCH from 10.2.
If TRUE this causes SQL profiles to target all SQL statements which have the sam
e text after normalizing all literal values into bind variables. (Note that if a
combination of literal values and bind values is used in a SQL statement, no bi
nd transformation occurs.) This is analogous to the matching algorithm used by t
he FORCE option of the cursor_sharing parameter.
Now the SQL profile is recreated with this option and after that it is used for
whatever literals. It internally replaces the literals to binds.
SQL> execute dbms_sqltune.accept_sql_profile(task_name =>'my_sql_tuning_task_2',
replace => TRUE, force_match=>true);
PL/SQL procedure successfully completed.
Now even if the literals are changed, the SQL profile gets used.
SQL> select /*+ no_index(test test_idx) */ * from test where n=10;
N
---------10
Execution Plan
---------------------------------------------------------Plan hash value: 2882402178
----------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 3 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| TEST_IDX | 1 | 3 | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------Predicate Information (identified by operation id):
--------------------------------------------------1 - access("N"=10)

Note
----- SQL profile "SYS_SQLPROF_014af9c167e84001" used for this statement
=> SQL profile getting used with different literal using force_match
This FORCE_MATCH option is very good feature which we can use it for SQLs using
literals so that the same execution plan is getting used.

Vous aimerez peut-être aussi