Sql tuning advisor was introduced by oracle from 10g onwards.  DBMS_SQLTUNE is the package , which helps the DBA’s in generating recommendations for bad sql queries.  Here we will use a simple query for sql tuning advisor and see what suggestion it is providing .

We will take below query:

select count(*) from bigtab where weight in ( select distinct( weight)  from bigtab);

 

 10:03:32 SQL > show user
USER is "SYS"
10:03:35 SQL > select count(*) from bigtab where weight in ( select distinct( weight)  from bigtab);

  COUNT(*)
----------
  13296640

Elapsed: 00:00:19.35

This query is taking around 19 seconds.

Lets generate the explain for this .

 

10:04:10 SQL > explain plan for
select count(*) from bigtab where weight in ( select distinct( weight)  from bigtab);10:04:34   2

Explained.

Elapsed: 00:00:00.09

10:05:15 SQL > select plan_table_output from
table(dbms_xplan.display('plan_table',null,'typical -cost -bytes'));10:05:32   2

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1575844597

------------------------------------------------------------
| Id  | Operation            | Name     | Rows  | Time     |
------------------------------------------------------------
|   0 | SELECT STATEMENT     |          |     1 | 00:11:11 |
|   1 |  SORT AGGREGATE      |          |     1 |          |
|*  2 |   HASH JOIN SEMI     |          |    13M| 00:11:11 |
|   3 |    TABLE ACCESS FULL | BIGTAB   |    13M| 00:02:28 |
|   4 |    VIEW              | VW_NSO_1 |    13M| 00:02:28 |
|   5 |     TABLE ACCESS FULL| BIGTAB   |    13M| 00:02:28 |

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("WEIGHT"="WEIGHT")

Note
-----
   - dynamic sampling used for this statement (level=2)

21 rows selected.

 

Now time to use the sql tuning advisor manually. It has three steps.

1. creating the tuning task

2. executing the tuning task

3. reporting tuning task.

 

Creating tuning task:

DECLARE
  my_task_name VARCHAR2(30);
  my_sqltext CLOB;
BEGIN
  my_sqltext := 'select count(*) from bigtab where weight in ( select distinct( weight)  from bigtab)';
my_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(
                           sql_text = > my_sqltext,
                           scope = > 'COMPREHENSIVE',
                           time_limit = > 60,
                           task_name = > 'TEST_sql_tuning_task1',
                           description = > 'Task to tune a query on a specified PRODUCT');
END;
/

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.04

Executing Tuning task:

 

10:06:08 SQL > Execute dbms_sqltune.Execute_tuning_task (task_name = > 'TEST_sql_tuning_task1');

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.20

Reporting tuning task:

 

10:06:21 SQL > set long 65536
set longchunksize 65536
set linesize 100
select dbms_sqltune.report_tuning_task('TEST_sql_tuning_task1') from dual;10:06:29 
10:06:29 SQL >

DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING_TASK1')
----------------------------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name   : TEST_sql_tuning_task1
Tuning Task Owner  : SYS
Workload Type      : Single SQL Statement
Scope              : COMPREHENSIVE
Time Limit(seconds): 60
Completion Status  : COMPLETED
Started at         : 07/20/2015 10:06:20
Completed at       : 07/20/2015 10:06:21


DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING_TASK1')
----------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Schema Name: SYS
SQL ID     : 22483tyaqab3r
SQL Text   : select count(*) from bigtab where weight in ( select distinct(
             weight)  from bigtab)

-------------------------------------------------------------------------------
FINDINGS SECTION (1 finding)
-------------------------------------------------------------------------------

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

DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING_TASK1')
----------------------------------------------------------------------------------------------------
--------------------------------------------------------
  A potentially better execution plan was found for this statement.

  Recommendation (estimated benefit<=10%)   ---------------------------------------   - Consider accepting the recommended SQL profile to use parallel execution     for this statement.     execute dbms_sqltune.accept_sql_profile(task_name =>
            'TEST_sql_tuning_task1', task_owner => 'SYS', replace => TRUE,
            profile_type => DBMS_SQLTUNE.PX_PROFILE);


DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING_TASK1')
----------------------------------------------------------------------------------------------------
  Executing this query parallel with DOP 64 will improve its response time
  -114609.79% over the original plan. However, there is some cost in enabling
  parallel execution. It will increase the statement's resource consumption by
  an estimated 7335026.74% which may result in a reduction of system
  throughput. Also, because these resources are consumed over a much smaller
  duration, the response time of concurrent statements might be negatively
  impacted if sufficient hardware capacity is not available.


DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING_TASK1')
----------------------------------------------------------------------------------------------------
 --------------------------------------------------

   5 - access("WEIGHT"="WEIGHT")

-------------------------------------------------------------------------------

DBMS_SQLTUNE.REPORT_TUNING_TASK('TEST_SQL_TUNING_TASK1')
----------------------------------------------------------------------------------------------------


Elapsed: 00:00:00.03

Below recommendation is provided in the report.

Recommendation (estimated benefit<=10%)
—————————————
– Consider accepting the recommended SQL profile to use parallel execution
for this statement.
execute dbms_sqltune.accept_sql_profile(task_name =>
‘TEST_sql_tuning_task1’, task_owner => ‘SYS’, replace => TRUE,
profile_type => DBMS_SQLTUNE.PX_PROFILE);

 

Lets implement this recommendation and check the performance again.

 

 execute dbms_sqltune.accept_sql_profile(task_name = >'TEST_sql_tuning_task1', task_owner = > 'SYS', replace = > TRUE, profile_type = > DBMS_SQLTUNE.PX_PROFIL
E);
PL/SQL procedure successfully completed.

Elapsed: 00:00:00.17

10:08:23 SQL > select plan_table_output from
table(dbms_xplan.display('plan_table',null,'typical -cost -bytes'));10:26:14 2

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 2143503231

-----------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Time | TQ |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 00:00:14 | | | |
| 1 | SORT AGGREGATE | | 1 | | | | |
| 2 | PX COORDINATOR | | | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10002 | 1 | | Q1,02 | P->S | QC (RAND) |
| 4 | SORT AGGREGATE | | 1 | | Q1,02 | PCWP | |
|* 5 | HASH JOIN SEMI | | 13M| 00:00:14 | Q1,02 | PCWP | |

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
| 6 | PX RECEIVE | | 13M| 00:00:03 | Q1,02 | PCWP | |
| 7 | PX SEND HASH | :TQ10000 | 13M| 00:00:03 | Q1,00 | P->P | HASH |
| 8 | PX BLOCK ITERATOR | | 13M| 00:00:03 | Q1,00 | PCWC | |
| 9 | TABLE ACCESS FULL | BIGTAB | 13M| 00:00:03 | Q1,00 | PCWP | |
| 10 | PX RECEIVE | | 13M| 00:00:03 | Q1,02 | PCWP | |
| 11 | PX SEND HASH | :TQ10001 | 13M| 00:00:03 | Q1,01 | P->P | HASH |
| 12 | VIEW | VW_NSO_1 | 13M| 00:00:03 | Q1,01 | PCWP | |
| 13 | PX BLOCK ITERATOR | | 13M| 00:00:03 | Q1,01 | PCWC | |
| 14 | TABLE ACCESS FULL| BIGTAB | 13M| 00:00:03 | Q1,01 | PCWP | |
-----------------------------------------------------------------------------------------------

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------

5 - access("WEIGHT"="WEIGHT")

Note
-----
- dynamic sampling used for this statement (level=2)
- automatic DOP: skipped because of IO calibrate statistics are missing
- SQL profile "SYS_SQLPROF_014eabca6e060000" used for this statement

32 rows selected.

10:07:27 SQL > select count(*) from bigtab where weight in ( select distinct( weight) from bigtab);

COUNT(*)
----------
13296640

Elapsed: 00:00:11.13

We can see the changes in the execution plan . Also the query which was taking 19 seconds before, is now taking 11 seconds.