Total Pageviews

Tuesday, July 17, 2018

How to tune a SQL Query using Oracle Advisory.

SQL> select name, open_mode from v$database;
 
NAME      OPEN_MODE
--------- --------------------
DB11GDEV  READ WRITE
 
SQL> select distinct sid from v$mystat;
 
       SID
    ----------
        62
 

Identify the sqlid of query that creating issue. For a demo purpose I identified a query which creates the issue (i.e  bkrm52bzasgd2). Below query will fetch the top sqls running on the database.

col type for a10
col username for a10
select
                (select username from dba_users where user_id = a.user_id) usernm,
                sql_id,
                plan_hash,
                type,
                cpu,
                wait,
                io,
                total
from (
select
     ash.inst_id, ash.user_id, ash.SQL_ID , ash.SQL_PLAN_HASH_VALUE Plan_hash, aud.name type,
     sum(decode(ash.session_state,'ON CPU',1,0))     cpu,
     sum(decode(ash.session_state,'WAITING',1,0))    -
     sum(decode(ash.session_state,'WAITING', decode(wait_class, 'User I/O',1,0),0))    wait ,
     sum(decode(ash.session_state,'WAITING', decode(wait_class, 'User I/O',1,0),0))    io ,
     sum(decode(ash.session_state,'ON CPU',1,1))     total
from gv$active_session_history ash,
     audit_actions aud
where SQL_ID is not NULL
   and ash.sql_opcode=aud.action
   and ash.sample_time > sysdate - &minutes /( 60*24)
group by inst_id, user_id, sql_id, SQL_PLAN_HASH_VALUE   , aud.name
order by sum(decode(session_state,'ON CPU',1,1))   desc
) a where  rownum <= 20
/
Enter value for minutes: 20 

USERNM     SQL_ID         PLAN_HASH TYPE              CPU       WAIT         IO      TOTAL

---------- ------------- ---------- ---------- ---------- ---------- ---------- ----------
FINANCE    bkrm52bzasgd2 3244424597 SELECT              5          0         54         59
SYS        5h7w8ykwtb2xt 4166561850 INSERT              0          0          1          1
SYS        1cq3qr774cu45 1031030155 INSERT              0          0          1          1
SYS        84qubbrsr0kfn 3675384499 INSERT              1          0          0          1

4 rows selected.

Elapsed: 00:00:00.01
 
Let’s create a tuning task id from below procedure.
 
SQL> set echo on
set time on
set timing on
set serveroutput on
declare
stmt_task VARCHAR2(40);
begin
stmt_task := DBMS_SQLTUNE.CREATE_TUNING_TASK(sql_id => 'bkrm52bzasgd2');
DBMS_OUTPUT.put_line('task_id: ' || stmt_task );
end;
/
task_id: TASK_5745
 
PL/SQL procedure successfully completed.
 
__________________________________________________________________________________
****************************Run the SQL TUNING TASK********************************
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 
14:21:55 SQL> EXEC DBMS_SQLTUNE.EXECUTE_TUNING_TASK(task_name => 'TASK_5745');
 
PL/SQL procedure successfully completed.
 
__________________________________________________________________________________
**********You can monitor the processing of the tuning task with the statement ************
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
 
14:22:38 SQL> SELECT TASK_NAME, STATUS FROM DBA_ADVISOR_LOG WHERE TASK_NAME = 'TASK_5745';
 
TASK_NAME                      STATUS
------------------------------ -----------
TASK_5745                      COMPLETED
 
14:22:44 SQL> SELECT TASK_NAME, STATUS,pct_completion_time,progress_metric FROM DBA_ADVISOR_LOG WHERE TASK_NAME = 'TASK_5745';
 
TASK_NAME                      STATUS      PCT_COMPLETION_TIME PROGRESS_METRIC
------------------------------ ----------- ------------------- ---------------
TASK_5745                      COMPLETED                     0               0
 
We can see our tuning advisory completed. Let’s see the recommendation as below:
 
14:22:50 SQL> set long 10000
set longchunksize 10000
set linesize 132
set pagesize 200
SQL> spool SQL_TUNE_bkrm52bzasgd2.log
SQL> SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK('TASK_5745') AS recommendations FROM dual;
 
RECOMMENDATIONS
------------------------------------------------------------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name   : TASK_5745
Tuning Task Owner  : SYS
Workload Type      : Single SQL Statement
Scope              : COMPREHENSIVE
Time Limit(seconds): 1800
Completion Status  : COMPLETED
Started at         : 07/17/2018 14:21:55
Completed at       : 07/17/2018 14:22:03
 
-------------------------------------------------------------------------------
Schema Name: FINANCE
SQL ID     : bkrm52bzasgd2
SQL Text   : select EMP_CODE,EMPLOYEE_NAME from
             finance.EMPLOYEE_RECORDS where EMPLOYEE_CODE>
             '41002'
 
-------------------------------------------------------------------------------
FINDINGS SECTION (2 findings)
-------------------------------------------------------------------------------
 
1- SQL Profile Finding (see explain plans section below)
--------------------------------------------------------
  A potentially better execution plan was found for this statement.
 
  Recommendation (estimated benefit: 93.06%)
  ------------------------------------------
  - Consider accepting the recommended SQL profile to use parallel execution
    for this statement.
execute dbms_sqltune.accept_sql_profile(task_name => 'TASK_5745',
task_owner => 'SYS', replace => TRUE, profile_type =>
DBMS_SQLTUNE.PX_PROFILE);
 
  Executing this query parallel with DOP 16 will improve its response time
  93.07% over the original plan. However, there is some cost in enabling
  parallel execution. It will increase the statement's resource consumption by
  an estimated 10.91% 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.
 
  The following data shows some sampled statistics for this SQL from the past
  week and projected weekly values when parallel execution is enabled.
 
                                 Past week sampled statistics for this SQL
                                 -----------------------------------------
  Number of executions                                                   0
  Percent of total activity                                              0
  Percent of samples with #Active Sessions > 2*CPU                       0
  Weekly DB time (in sec)                                                0
 
                              Projected statistics with Parallel Execution
                              --------------------------------------------
  Weekly DB time (in sec)                                                0
 
2- Index Finding (see explain plans section below)
--------------------------------------------------
  The execution plan of this statement can be improved by creating one or more indices.
 
  Recommendation (estimated benefit: 99.92%)
  ------------------------------------------
  - Consider running the Access Advisor to improve the physical schema design
    or creating the recommended index.
create index FINANCE.IDX$$_166D0001 on
FINANCE.EMPLOYEE_RECORDS(EMP_CODE","EMPLOYEE_NAME");
 
  Rationale
  ---------
    Creating the recommended indices significantly improves the execution plan
    of this statement. However, it might be preferable to run "Access Advisor"
    using a representative SQL workload as opposed to a single statement. This
    will allow to get comprehensive index recommendations which takes into
    account index maintenance overhead and additional space consumption.
 
-------------------------------------------------------------------------------
EXPLAIN PLANS SECTION
-------------------------------------------------------------------------------
 
1- Original
-----------
Plan hash value: 3244424597
 
----------------------------------------------------------------------------------------------
| Id  | Operation         | Name                     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                          | 40817 |   438K| 92696   (1)| 00:18:33 |
|*  1 |  TABLE ACCESS FULL| MATERIAL_RECORDS_TESTBKP | 40817 |   438K| 92696   (1)| 00:18:33 |
----------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("ILI_MATERIAL_NUMBER">'A41002')
 
2- Using New Indices
--------------------
Plan hash value: 944928231
 
---------------------------------------------------------------------------------------
| Id  | Operation            | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                | 40817 |   438K|    65   (2)| 00:00:01 |
|*  1 |  INDEX FAST FULL SCAN| IDX$$_166D0001 | 40817 |   438K|    65   (2)| 00:00:01 |
---------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("ILI_MATERIAL_NUMBER">'A41002')
 
3- Using Parallel Execution
---------------------------
Plan hash value: 1097799476
 
------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation            | Name                     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                          | 40817 |   438K|  6425   (0)| 00:01:18 |        |      |            |
|   1 |  PX COORDINATOR      |                          |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)| :TQ10000                 | 40817 |   438K|  6425   (0)| 00:01:18 |  Q1,00 | P->S | QC (RAND)  |
|   3 |    PX BLOCK ITERATOR |                          | 40817 |   438K|  6425   (0)| 00:01:18 |  Q1,00 | PCWC |            |
|*  4 |     TABLE ACCESS FULL| MATERIAL_RECORDS_TESTBKP | 40817 |   438K|  6425   (0)| 00:01:18 |  Q1,00 | PCWP |            |
------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   4 - filter("ILI_MATERIAL_NUMBER">'A41002')
 
-------------------------------------------------------------------------------
 
 
14:23:05 SQL> select * from dba_sql_profiles;
 
no rows selected
 
We have two findings by advisor. Either we can do SQL profiling or create one or more indexes. Profiling will execute the query fast but required more resources. Let’s implement 2nd advisory which will improve the performance of query by creating one or more indices. This will reduce the cost from  92696 to 65.  
 
14:32:18 SQL> create index FINANCE.IDX$$_166D0001 on
FINANCE.EMPLOYEE_RECORDS(EMP_CODE","EMPLOYEE_NAME");
 
Now we are gathering the stat to get the effective result.
SQL>
exec DBMS_STATS.GATHER_TABLE_STATS (ownname => 'FINANCE' , tabname => ' EMPLOYEE_RECORDS',cascade => true, estimate_percent => 5,method_opt=>'for all indexed columns size 1', granularity => 'ALL', degree => 1);
 
Let’s check the active plan and see if the cost reduced as below query.
 
8:10:19 SQL>  select plan_table_output from table(dbms_xplan.display_cursor('&sql_id',&child));
 
Enter value for sql_id: bkrm52bzasgd2
Enter value for child: 0
 
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  bkrm52bzasgd2, child number 0
-------------------------------------
select EMP_CODE,EMPLOYEE_NAME from
             finance.EMPLOYEE_RECORDS where EMPLOYEE_CODE>
             '41002'
 
 
Plan hash value: 944928231
 
---------------------------------------------------------------------------------------
| Id  | Operation            | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                |       |       |    57 (100)|          |
|*  1 |  INDEX FAST FULL SCAN| IDX$$_166D0001 | 34637 |   372K|    57   (2)| 00:00:01 |
---------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("ILI_MATERIAL_NUMBER">'A41002')
 
 
19 rows selected.
 
We can see the cost reduced to 57 and now the query takes only 00:00:01 seconds to complete.
 

No comments:

Post a Comment