从上述显示内容可以看出,目标SQL走的是对表T1的全表扫描(Table Access Full),这个执行计划显然是错误,这里正确的执行坟墓应该是走索引IDX_T1的索引范围扫描(Index Range Scan)。下面使用SQL Tuning Advisor对这条SQL生成Automatic类型的SQL Profile。
a.先创建一个名为my_sql_tuning_task_2的自动调整任务:
zx@MYDB>declare
2 my_task_name varchar2(30);
3 my_sqltext clob;
4 begin
5 my_sqltext:='select /*+no_index(t1 idx_t1) */ * from t1 where n=1';
6 my_task_name:=dbms_sqltune.create_tuning_task(
7 sql_text=>my_sqltext,
8 user_name=>USER,
9 scope=>'COMPREHENSIVE',
10 time_limit=>60,
11 task_name=>'my_sql_tuning_task_1',
12 description=>'Task to tune a query on table t1');
13 end;
14 /
PL/SQL procedure successfully completed.
zx@MYDB>select task_name,status,execution_start,execution_end from user_advisor_log;
TASK_NAME STATUS EXECUTION_START EXECUTION_END
------------------------------ --------------------------------- ------------------- -------------------
my_sql_tuning_task_1 INITIAL
注:创建任务时可以使用SQL来创建,可以适用于SQL文本长的情况。详情参考官方文档。
b.执行上述自动调整任务
zx@MYDB>begin
2 dbms_sqltune.execute_tuning_task(task_name=>'my_sql_tuning_task_1');
3 end;
4 /
zx@MYDB>zx@MYDB>select task_name,status,execution_start,execution_end from user_advisor_log;
TASK_NAME STATUS EXECUTION_START EXECUTION_END
------------------------------ --------------------------------- ------------------- -------------------
my_sql_tuning_task_1 COMPLETED 2017-02-28 10:59:43 2017-02-28 10:59:44
PL/SQL procedure successfully completed.
c.查看上述自动任务的调整结果
zx@MYDB>set long 9000
zx@MYDB>set longchunksize 1000
zx@MYDB>set linesize 800
zx@MYDB>select dbms_sqltune.report_tuning_task('my_sql_tuning_task_1') from dual;
从上述调整结果可以看到,Oracle现在告诉我们:它已经为目标SQL找到了更好的执行计划,并且已经创建了针对该SQL的Automatic类型的SQL Profile。如果我们使用accecp_sql_profile接受了这个SQL Profile,则目标SQL的响应时间将会有86.24%的提升,逻辑读将会有95%的提升,并且接受了该SQL Profile后目标SQL的执行计划将会由原来的全表扫描变为索引范围扫描。
上面Automatic类型的SQL Profile所产生的调整结果就是我们想要的,所以现在只需按Oracle的提示接受这个SQL Profile即可:
zx@MYDB>execute dbms_sqltune.accept_sql_profile(task_name =>'my_sql_tuning_task_1', task_owner => 'ZX', replace => TRUE,force_match=>true);
PL/SQL procedure successfully completed.
接受此SQL Profile后我们来看一下效果,再次执行目标SQL:
zx@MYDB>select /*+no_index(t1 idx_t1) */ * from t1 where n=1;
N
----------
1