本次演示sql profile 的基本用法, 平台基于rhel6 +oracle11.2 版本
第一节建立测试用例
第二节查看sql的执行计划,本次所有试验也是通过sql profile 来使得第二节1部分的sql执行计划变成第二节2部分的执行计划
第三节是通过sql tuning advisor 生成sql profile ,使得sql的执行计划改变
第四节是通过sql tuning advisor 生成sql profile 的缺点
第五节是手工建造sql profile ,使得sql的执行计划改变
第六节是通过coe_xfr_sql_profile.sql 脚本 来修改已存在sql的执行计划
第七节是sql profile的基本语法
一、建立测试用例
SQL> create table t1 as selectobject_id,object_name from dba_objects where rownum<=50000; Table created. SQL> create table t2 as select * fromdba_objects; Table created. SQL> create index t2_idx ont2(object_id); Index created. SQL> execdbms_stats.gather_table_stats(user,'t1',cascade=>true,method_opt=>'forall columns size 1'); PL/SQL procedure successfully completed. SQL> execdbms_stats.gather_table_stats(user,'t2',cascade=>true,method_opt=>'forall columns size 1'); PL/SQL procedure successfully completed.
二、查看sql执行计划
1、查看原始的执行计划
SQL> set autotrace traceonly; SQL> select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id; 41 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 1838229974 --------------------------------------------------------------------------- | Id | Operation | Name |Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0| SELECT STATEMENT | | 700 | 23100 | 68 (0)| 00:00:01 | |* 1| HASH JOIN | | 700 | 23100 | 68 (0)| 00:00:01 | |* 2| TABLE ACCESS FULL| T1 | 700 | 16100 | 17 (0)| 00:00:01 | | 3| TABLE ACCESS FULL| T2 |13997 | 136K | 51 (0)| 00:00:01 | --------------------------------------------------------------------------- Predicate Information (identified byoperation id): --------------------------------------------------- 1-access("T1"."OBJECT_ID"="T2"."OBJECT_ID") 2- filter("T1"."OBJECT_NAME" LIKE '%T1%' AND"T1"."OBJECT_NAME" IS NOT NULL) Statistics ---------------------------------------------------------- 38 recursive calls 0 db block gets 295 consistent gets 0 physical reads 0 redo size 2221 bytes sent via SQL*Net toclient 545 bytes received via SQL*Netfrom client 4 SQL*Net roundtrips to/fromclient 10 sorts (memory) 0 sorts (disk) 41 rows processed
2、查看加入hint后的执行计划,逻辑读少了
SQL> select /*+ use_nl(t1 t2) index(t2)*/ t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id; 41 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 1022743391 --------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time | -------------------------------------------------------------------------------------- | 0| SELECT STATEMENT | | 700 | 23100 | 1418 (1)| 00:00:18 | | 1| NESTED LOOPS | | 700 | 23100 | 1418 (1)| 00:00:18 | | 2| NESTED LOOPS | | 700 | 23100 | 1418 (1)| 00:00:18 | |* 3| TABLE ACCESS FULL |T1 | 700 | 16100 | 17 (0)| 00:00:01 | |* 4| INDEX RANGE SCAN |T2_IDX | 1| | 1 (0)| 00:00:01 | | 5| TABLE ACCESS BY INDEX ROWID| T2 | 1 | 10 | 2 (0)| 00:00:01 | --------------------------------------------------------------------------------------- Predicate Information (identified byoperation id): --------------------------------------------------- 3- filter("T1"."OBJECT_NAME" LIKE '%T1%' AND"T1"."OBJECT_NAME" IS NOT NULL) 4-access("T1"."OBJECT_ID"="T2"."OBJECT_ID") Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 127 consistent gets 0 physical reads 0 redo size 2221 bytes sent via SQL*Net toclient 545 bytes received via SQL*Netfrom client 4 SQL*Net roundtrips to/fromclient 0 sorts (memory) 0 sorts (disk) 41 rows processed SQL> SET AUTOTRACE OFF;
三、通过SQL Tuning Advisor生成SQL PROFILE
查看sql_id 为 : awxu67tt24sz0
SQL> select sql_id,SQL_TEXT from v$sqlarea where sql_text like '%selectt1.*,t2.owner from t1,t2 where t1.object_name%'; SQL_ID SQL_TEXT --------------------------------------------------------------------------------------------- awxu67tt24sz0 selectt1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_
1、执行过程 sql tuning advisor
SQL> var tuning_task varchar2(100);
SQL> DECLARE
l_sql_id v$session.prev_sql_id%TYPE;
l_tuning_task VARCHAR2(30);
BEGIN
l_sql_id:='awxu67tt24sz0';
l_tuning_task:= dbms_sqltune.create_tuning_task(sql_id => l_sql_id);
:tuning_task:=l_tuning_task;
dbms_sqltune.execute_tuning_task(l_tuning_task);
dbms_output.put_line(l_tuning_task);
END;
/
2、查看task名称
SQL> print tuning_task;
tuning_task
---------
任务_82
3、查看sql tuning advisor执行报告
SQL> set long 99999
SQL> col comments format a200
SQL> SELECT dbms_sqltune.report_tuning_task(:tuning_task)COMMENTS FROM dual;
COMMENTS
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name : 任务_82
Tuning Task Owner : SYSTEM
Workload Type : Single SQL Statement
Scope : COMPREHENSIVE
Time Limit(seconds): 1800
Completion Status : COMPLETED
Started at : 10/26/2017 17:43:03
Completed at : 10/26/2017 17:43:03
-------------------------------------------------------------------------------
Schema Name: SYS
SQL ID : awxu67tt24sz0
SQL Text : select t1.*,t2.owner from t1,t2where t1.object_name like
'%T1%' and t1.object_id=t2.object_id
-------------------------------------------------------------------------------
FINDINGS SECTION (1 finding)
-------------------------------------------------------------------------------
1- SQL Profile Finding (see explain planssection below)
--------------------------------------------------------
为此语句找到了性能更好的执行计划。
Recommendation (estimated benefit: 51.32%)
------------------------------------------
- 考虑接受推荐的 SQL概要文件。
executedbms_sqltune.accept_sql_profile(task_name => '任务_82', task_owner
=>'SYSTEM', replace => TRUE);
Validation results
------------------
已对 SQLprofile 进行测试, 方法为执行其计划和原始计划并测量与计划相对应的执行统计信息。如果其中一个计划运行在很短的时间内就完成,
则另一计划可能只执行了一部分。
Original Plan With SQL Profile % Improved
------------- ---------------- ----------
Completion Status: COMPLETE COMPLETE
Elapsed Time (s): .00709 .006333 10.67 %
CPUTime (s): .00709 .006255 11.77 %
User I/O Time (s): 0 0
Buffer Gets: 243 118 51.44 %
Physical Read Requests: 0 0
Physical Write Requests: 0 0
Physical Read Bytes: 0 0
Physical Write Bytes: 0 0
Rows Processed: 41 41
Fetches: 41 41
Executions: 1 1
Notes
-----
1.the original plan 的统计信息是 10 执行的平均值。
2.the SQL profile plan 的统计信息是 10 执行的平均值。
-------------------------------------------------------------------------------
EXPLAIN PLANS SECTION
-------------------------------------------------------------------------------
1- Original With Adjusted Cost
------------------------------
Plan hash value: 1838229974
---------------------------------------------------------------------------
| Id | Operation | Name |Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0| SELECT STATEMENT | | 41 | 1353 | 68 (0)| 00:00:01 |
|* 1| HASH JOIN | | 41 | 1353 | 68 (0)| 00:00:01 |
|* 2| TABLE ACCESS FULL| T1 | 41 | 943 | 17 (0)| 00:00:01 |
| 3| TABLE ACCESS FULL| T2 | 13997 | 136K| 51 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified byoperation id):
---------------------------------------------------
1-access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
2- filter("T1"."OBJECT_NAME" LIKE '%T1%' AND"T1"."OBJECT_NAME" IS
NOT NULL)
2- Using SQL Profile
--------------------
Plan hash value: 3787413387
----------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
----------------------------------------------------------------------
| 0| SELECT STATEMENT | | 1 | 53 | 11 |
| 1| TABLE ACCESS BY INDEX ROWID| T2 | 1 | 30 | 2 |
| 2| NESTED LOOPS | | 1 | 53 | 11 |
|* 3| TABLE ACCESS FULL | T1 | 1 | 23 | 9 |
|* 4| INDEX RANGE SCAN | T2_IDX | 1 | | 1 |
----------------------------------------------------------------------
Predicate Information (identified byoperation id):
---------------------------------------------------
3- filter("T1"."OBJECT_NAME" LIKE '%T1%')
4-access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
-------------------------------------------------------------------------------
tuning_task
---------
任务_82
4、接受建议(上述第3步的红字部分)
SQL> executedbms_sqltune.accept_sql_profile(task_name => '任务_82',task_owner=> 'SYSTEM', replace => TRUE);
5、再次执行之前sql,查看执行计划已按照sql profile建议调优
SQL> set autotrace traceonly;
SQL> select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id;41 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3787413387
----------------------------------------------------------------------
| Id | Operation |Name | Rows | Bytes | Cost |
----------------------------------------------------------------------
| 0| SELECT STATEMENT | | 1 | 53 | 11 |
| 1| TABLE ACCESS BY INDEX ROWID| T2 | 1 | 30 | 2 |
| 2| NESTED LOOPS | | 1 | 53 | 11 |
|* 3| TABLE ACCESS FULL | T1 | 1 | 23 | 9 |
|* 4| INDEX RANGE SCAN | T2_IDX | 1 | | 1 |
----------------------------------------------------------------------
Predicate Information (identified byoperation id):
---------------------------------------------------
3- filter("T1"."OBJECT_NAME" LIKE '%T1%')
4-access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
Note
-----
-cpu costing is off (consider enabling it)
- SQL profile "SYS_SQLPROF_015f589bcf270000" used for this statementStatistics
----------------------------------------------------------
34 recursive calls
0 db block gets
137 consistent gets
1 physical reads
0 redo size
2221 bytes sent via SQL*Net toclient
545 bytes received via SQL*Netfrom client
4 SQL*Net roundtrips to/fromclient
1 sorts (memory)
0 sorts (disk)
41 rows processed
SQL> SET AUTOTRACE OFF;6、查看一下SQL Profile信息(上述第5步的红字部分)
SQL> select name,category,signature,type,status,force_matchingfrom dba_sql_profiles where name='SYS_SQLPROF_015f589bcf270000'; NAME CATEGORY SIGNATURE TYPE STATUS FORCE_MATCHING ---------------------------- ---------- ------------ ---------- ---------- --------------- SYS_SQLPROF_015f589bcf270000 DEFAULT 8.97554102 MANUAL ENABLED NO
四、通过SQL Tuning Advisor生成SQL PROFILE 的不足
1、查看SQL Profiles实际内容
SQL> select name,category,signature,type,status,force_matching from dba_sql_profiles where name='SYS_SQLPROF_015f589bcf270000';
SIGNATURE CATEGORY OBJ_TYPE PLAN_ID COMP_DATA SPARE1 SPARE2
----------------- ----------------- ------------------------- ----------
8.97554102 DEFAULT 1 0 <outline_data><hint><![CDATA[OPT_ESTIMATE(@"SEL$1",TABLE, "T1"@"SEL$1",SCALE_ROWS=0.05858816805)]]></hint><hint><![CDATA[IGNORE_OPTIM_EMBEDDED_HINTS]]></hint><hint><![CDATA[OPTIMIZER_FEATURES_ENABLE('8.1.5')]]></hint></outline_data>
说明:
可以看到,SQL Profiles的attr_val实际上就是一些Hints,这跟Outlines没有本质上的区别。只是SQL Profiles中的Hint,没有指定SQL使用哪个索引,也没有指定表的连接方法和连接顺序。这里只指定了T1表评估返回的行数,与原始的评估返回的行数的放大缩小的倍数。700*0.05858816805正好为41。这里就是告诉Oracle优化器,T1表经过谓语过滤后返回行数应该为评估的0.05858816805倍。从这里可以看出,SQLProfiles并不会锁定SQL的执行计划,只是提供了更多、更准确的统计信息给优化器。
2、修改T1表统计信息,再次查看SQL PROFILE的执行计划已改变
SQL> exec dbms_stats.set_table_stats('SYS','T1',numrows=>50000000); PL/SQL procedure successfully completed. SQL> set autotrace traceonly; SQL> select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id; 41 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 1838229974 ----------------------------------------------------------- | Id | Operation | Name |Rows | Bytes | Cost | ----------------------------------------------------------- | 0 | SELECT STATEMENT | | 271 | 14363 | 38 | |* 1 | HASH JOIN | | 271 | 14363 | 38 | |* 2 | TABLE ACCESS FULL| T1 | 271 | 6233 | 9 | | 3 | TABLE ACCESS FULL| T2 | 13997 | 410K| 28 | ----------------------------------------------------------- Predicate Information (identified byoperation id): --------------------------------------------------- 1 -access("T1"."OBJECT_ID"="T2"."OBJECT_ID") 2 - filter("T1"."OBJECT_NAME" LIKE '%T1%') Note ----- - cpu costing is off (consider enabling it) - SQL profile "SYS_SQLPROF_015f589bcf270000" used for thisstatement Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 250 consistent gets 0 physical reads 0 redo size 2221 bytes sent via SQL*Net toclient 545 bytes received via SQL*Netfrom client 4 SQL*Net roundtrips to/fromclient 0 sorts (memory) 0 sorts (disk) 41 rows processed SQL> SET AUTOTRACE OFF;
说明:
将T1表的统计信息中的表行数改为5000万,Oracle的执行计划又变回为full scan+hash join。可以看到,虽然SQL Profile起作用了,但是并没有锁定执行计划。
五、手工创建 SQL PROFILES
1、删除第三步,通过sql tuning advisor 生成的 sql profile
SQL> execdbms_sqltune.drop_sql_profile('SYS_SQLPROF_015f589bcf270000'); PL/SQL procedure successfully completed
SQL> exec dbms_stats.gather_table_stats(user,'t1',cascade=>true,method_opt=>'forall columns size 1');
2、手工创建 sql profile
查看profile的参数SYS.SQLPROF_ATTR SQL> select text from dba_source where name='SQLPROF_ATTR' and owner='SYS'; TEXT -------------------------------------------------------------------------------- TYPE sqlprof_attr AS VARRAY(2000) of VARCHAR2(500) 手工创建sql profile SQL> declare 2 v_hints sys.sqlprof_attr; 3 begin 4 v_hints:=sys.sqlprof_attr('USE_NL(T1@SEL$1T2@SEL$1)','INDEX(T2@SEL$1)'); 5 dbms_sqltune.import_sql_profile('select t1.*,t2.owner from t1,t2 where t1.object_name like ''%T1%'' and t1.object_id=t2.object_id',v_hints,'SQLPROFILE_NAME1',force_match=>true,replace=>true); 6 end; 7 / PL/SQL procedure successfully completed. 查看创建后的sql profile信息 SQL> select b.comp_data from dba_sql_profiles a, sys.sqlobj$data b where a.signature = b.signature and a.name='SQLPROFILE_NAME1'; COMP_DATA --------------- <outline_data><hint><![CDATA[USE_NL(T1T2)]]></hint> <hint><![CDATA[INDEX(T2)]]></hint></outline_data>
3、查看sql执行计划,已改变成最优的执行计划
SQL> set autotrace traceonly; SQL> select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id; 41 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 1022743391 -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 700 | 23100 | 1418 (1)| 00:00:18 | | 1 | NESTED LOOPS | | 700 | 23100 | 1418 (1)| 00:00:18 | | 2 | NESTED LOOPS | | 700 | 23100 | 1418 (1)| 00:00:18 | |* 3 | TABLE ACCESS FULL | T1 | 700 | 16100 | 17 (0)| 00:00:01 | |* 4 | INDEX RANGE SCAN | T2_IDX | 1 | | 1 (0)| 00:00:01 | | 5 | TABLE ACCESS BY INDEX ROWID|T2 | 1 | 10 | 2 (0)| 00:00:01 | --------------------------------------------------------------------------------------- Predicate Information (identified byoperation id): --------------------------------------------------- 3- filter("T1"."OBJECT_NAME" LIKE '%T1%' AND"T1"."OBJECT_NAME" IS NOT NULL) 4- access("T1"."OBJECT_ID"="T2"."OBJECT_ID") Note ----- - SQL profile "SQLPROFILE_NAME1" used for this statement Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 127 consistent gets 0 physical reads 0 redo size 2221 bytes sent via SQL*Net toclient 545 bytes received via SQL*Netfrom client 4 SQL*Net roundtrips to/fromclient 0 sorts (memory) 0 sorts (disk) 41 rows processed SQL> SET AUTOTRACE OFF;
4、修改T1表统计信息,再次验证SQL PROFILE的执行计划不变
SQL> exec dbms_stats.set_table_stats('SYS','T1',numrows=>50000000); PL/SQL procedure successfully completed. SQL> set autotrace traceonly; SQL> select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id; 41 rows selected. Execution Plan ---------------------------------------------------------- Plan hash value: 1022743391 -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |Cost (%CPU)| Time | | 0 | SELECT STATEMENT | | 2500K| 78M| 5002K (1)| 16:40:26 | | 1 | NESTED LOOPS | | 2500K| 78M| 5002K (1)| 16:40:26 | | 2 | NESTED LOOPS | | 2500K| 78M| 5002K (1)| 16:40:26 | |* 3 | TABLE ACCESS FULL | T1 | 2500K| 54M| 554 (97)| 00:00:07 | |* 4 | INDEX RANGE SCAN | T2_IDX | 1 | | 1 (0)| 00:00:01 | | 5 | TABLE ACCESS BY INDEX ROWID|T2 | 1 | 10 | 2 (0)| 00:00:01 | -------------------------------------------------------------------------------- Predicate Information (identified byoperation id): --------------------------------------------------- 3- filter("T1"."OBJECT_NAME" LIKE '%T1%' AND"T1"."OBJECT_NAME" IS NOT NULL) 4-access("T1"."OBJECT_ID"="T2"."OBJECT_ID") Note ----- - SQL profile "SQLPROFILE_NAME1" used for this statement Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 131 consistent gets 0 physical reads 0 redo size 2221 bytes sent via SQL*Net toclient 545 bytes received via SQL*Netfrom client 4 SQL*Net roundtrips to/fromclient 0 sorts (memory) 0 sorts (disk) 41 rows processed SQL> SET AUTOTRACE OFF;
六、修改已存在sql的执行计划
在原有sql上加入/*+ coe_xfr_sql_profile */ hint,使得执行计划为t1和t2表的 fullscan+hash join,然后用coe_xfr_sql_profile.sql 脚本改变sql的执行计划为indexrange scan+nested loop
1、重新收集一下T1的表统计信息
SQL> exec dbms_stats.gather_table_stats(user,'t1',cascade=>true,method_opt=>'forall columns size 1');
2、先看一下上述第五步的sql 执行计划的PLAN_TABLE_OUTPUT
SQL> select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' andt1.object_id=t2.object_id;
41 rows selected.
SQL>select * fromtable(dbms_xplan.display_cursor(null,null,'outline'));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID 4zbqykx89yc8v, child number 0
-------------------------------------
select t1.*,t2.owner from t1,t2 wheret1.object_name like '%T1%' and
t1.object_id=t2.object_id
Plan hash value: 1022743391
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | | | 1418 (100)||
| 1 | NESTED LOOPS | | 700 | 23100 | 1418 (1)| 00:00:18 |
| 2 | NESTED LOOPS | | 700 | 23100 | 1418 (1)| 00:00:18 |
|* 3 | TABLE ACCESS FULL |T1 | 700 | 16100 | 17 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | T2_IDX | 1 | | 1 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID|T2 | 1 | 10 | 2 (0)| 00:00:01 |
Outline Data
-------------
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
OPTIMIZER_FEATURES_ENABLE('11.2.0.4')
DB_VERSION('11.2.0.4')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
FULL(@"SEL$1" "T1"@"SEL$1")
INDEX(@"SEL$1" "T2"@"SEL$1"("T2"."OBJECT_ID"))
LEADING(@"SEL$1" "T1"@"SEL$1""T2"@"SEL$1")
USE_NL(@"SEL$1" "T2"@"SEL$1")
NLJ_BATCHING(@"SEL$1" "T2"@"SEL$1")
END_OUTLINE_DATA
*/
Predicate Information (identified byoperation id):
---------------------------------------------------
3- filter(("T1"."OBJECT_NAME" LIKE '%T1%' AND"T1"."OBJECT_NAME" IS NOT NULL))
4- access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
Note
-----
- SQL profile SQLPROFILE_NAME1 used for this statement
41 rows selected.
3、执行带有/*+ coe_xfr_sql_profile */ hint的语句,执行计划是t1和t2表的full scan+hash join
SQL> set autotrace traceonly;
SQL> select /*+ coe_xfr_sql_profile */ t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id;
41 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1838229974
---------------------------------------------------------------------------
| Id | Operation | Name |Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 700 | 23100 | 68 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 700 | 23100 | 68 (0)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| T1 | 700 | 16100 | 17 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T2 | 13997 | 136K| 51 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified byoperation id):
---------------------------------------------------
1 -access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
2 - filter("T1"."OBJECT_NAME" LIKE '%T1%' AND"T1"."OBJECT_NAME" IS
NOT NULL)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
246 consistent gets
0 physical reads
0 redo size
2221 bytes sent via SQL*Net toclient
545 bytes received via SQL*Netfrom client
4 SQL*Net roundtrips to/fromclient
0 sorts (memory)
0 sorts (disk)
41 rows processed
SQL> SET AUTOTRACE OFF;
4、查看上述第2步的sql_id,PLAN_HASH_VALUE如下:
SQL> selecta.sql_text,a.sql_id,a.PLAN_HASH_VALUE from v$sqlarea a where a.sql_text like'%/*+ coe_xfr_sql_profile */%';
SQL_TEXT SQL_ID PLAN_HASH_VALUE
-------------------------------------------------- ------------------------------ ------------------------
select /*+ coe_xfr_sql_profile */ t…… dagpvm5f8yq2t 1838229974
5、执行coe_xfr_sql_profile.sql脚本,输入上述第3步sql_id和PLAN_HASH_VALUE值,会生成一个名字为coe+sql_id+plan_hash_value的coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql文件
SQL> @/u01/oracle_setup/coe_xfr_sql_profile.sql
Parameter 1:
SQL_ID (required)
Enter value for 1: dagpvm5f8yq2t
Execution Plan
----------------------------------------------------------
Plan hash value: 3235375904
--------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
--------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 130 | 27 (19)| 00:00:01 | | |
| 1 | SORT ORDER BY | | 2 | 130 | 27 (19)| 00:00:01 | | |
|* 2 | HASH JOIN OUTER | | 2 | 130 | 26 (16)| 00:00:01 | | |
|* 3 | HASH JOIN OUTER | | 2 | 78 | 18 (17)| 00:00:01 | | |
| 4 | VIEW | | 2 | 26 | 17 (12)| 00:00:01 | | |
| 5 | SORT UNIQUE | | 2 | 2111 | 17 (12)| 00:00:01 | | |
| 6 | UNION-ALL | | | | | | | |
|* 7 | FIXED TABLE FIXEDINDEX | X$KQLFXPL (ind:4) | 1 | 2023 | 0 (0)| 00:00:01 | | |
|* 8 | TABLE ACCESS BY INDEXROWID | WRH$_SQL_PLAN | 1 | 88 | 15 (0)| 00:00:01 | | |
|* 9 | INDEX SKIP SCAN | WRH$_SQL_PLAN_PK | 12 | | 13 (0)| 00:00:01 | | |
| 10 | VIEW | | 1 | 26 | 1 (100)| 00:00:01 | | |
| 11 | HASH GROUP BY | | 1 | 47 | 1 (100)| 00:00:01 | | |
|* 12 | FIXED TABLE FIXED INDEX | X$KGLCURSOR_CHILD (ind:2) | 1 | 47 | 0 (0)| 00:00:01 | | |
| 13 | VIEW | | 3 | 78 | 8 (13)| 00:00:01 | | |
| 14 | HASH GROUP BY | | 3 | 174 | 8 (13)| 00:00:01 | | |
| 15 | NESTED LOOPS | | 3 | 174 | 7 (0)| 00:00:01 | | |
| 16 | NESTED LOOPS | | 3 | 174 | 7 (0)| 00:00:01 | | |
| 17 | PARTITION RANGEALL | | 3 | 129 | 6 (0)| 00:00:01 | 1 | 2 |
|* 18 | TABLE ACCESS BY LOCAL INDEX ROWID|WRH$_SQLSTAT | 3 | 129 | 6 (0)| 00:00:01 | 1 | 2 |
|* 19 | INDEX RANGE SCAN | WRH$_SQLSTAT_INDEX | 3 | | 3 (0)| 00:00:01 | 1 | 2 |
|* 20 | INDEX UNIQUE SCAN | WRM$_SNAPSHOT_PK | 1 | | 0 (0)| 00:00:01 | | |
|* 21 | TABLE ACCESS BY INDEX ROWID | WRM$_SNAPSHOT | 1 | 15 | 1 (0)| 00:00:01 | | |
--------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified byoperation id):
---------------------------------------------------
2 - access("P"."PLAN_HASH_VALUE"="A"."PLAN_HASH_VALUE"(+))
3 -access("P"."PLAN_HASH_VALUE"="M"."PLAN_HASH_VALUE"(+))
7 - filter("KQLFXPL_SQLID"='dagpvm5f8yq2t' AND"KQLFXPL_OTHER_XML" IS NOT NULL)
8 - filter("OTHER_XML" IS NOT NULL)
9 - access("SQL_ID"='dagpvm5f8yq2t')
filter("SQL_ID"='dagpvm5f8yq2t')
12 - filter("KGLOBT03"='dagpvm5f8yq2t' AND"KGLOBT05">0)
18 - filter("EXECUTIONS_TOTAL">0)
19 - access("SQL_ID"='dagpvm5f8yq2t')
20 -access("SN"."DBID"="SQL"."DBID" AND"SN"."SNAP_ID"="SQL"."SNAP_ID" AND"SN"."INSTANCE_NUMBER"="SQL"."INSTANCE_NUMBER")
21 - filter("SN"."STATUS"=0)
Statistics
----------------------------------------------------------
348 recursive calls
0 db block gets
102 consistent gets
5 physical reads
124 redo size
613 bytes sent via SQL*Net toclient
523 bytes received via SQL*Netfrom client
2 SQL*Net roundtrips to/fromclient
15 sorts (memory)
0 sorts (disk)
1 rows processed
Parameter 2:
PLAN_HASH_VALUE (required)
Enter value for 2: 1838229974
Values passed to coe_xfr_sql_profile:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SQL_ID : "dagpvm5f8yq2t"
PLAN_HASH_VALUE: "1838229974"
SQL>BEGIN
2 IF :sql_text IS NULL THEN
3 RAISE_APPLICATION_ERROR(-20100, 'SQL_TEXT for SQL_ID &&sql_id.was not found in memory (gv$sqltext_with_newlines) or AWR (dba_hist_sqltext).');
4 END IF;
5 END;
6 /
SQL>SET TERM OFF;
SQL>BEGIN
2 IF :other_xml IS NULL THEN
3 RAISE_APPLICATION_ERROR(-20101, 'PLAN for SQL_ID &&sql_id. andPHV &&plan_hash_value. was not found in memory (gv$sql_plan) or AWR(dba_hist_sql_plan).');
4 END IF;
5 END;
6 /
SQL>SET TERM OFF;
Execute coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql
on TARGET system in order to create acustom SQL Profile
with plan 1838229974 linked to adjustedsql_text.
COE_XFR_SQL_PROFILE completed.
6、查看生成的coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql文件
[oracle@oracle11g ~]$ morecoe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql
SPOcoe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.log;
SET ECHO ON TERM ON LIN 2000 TRIMS ONNUMF 99999999999999999999;
REM
REM $Header: 215187.1coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql 11.4.3.5 2017/10/27carlos.sierra $
REM
REM Copyright (c) 2000-2011, OracleCorporation. All rights reserved.
REM
REM AUTHOR
REM
REM SCRIPT
REM coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql
REM
REM DESCRIPTION
REM This script is generated by coe_xfr_sql_profile.sql
REM It contains the SQL*Plus commands to create a custom
REM SQL Profile for SQL_ID dagpvm5f8yq2t based on plan hash
REM value 1838229974.
REM The custom SQL Profile to be created by this script
REM will affect plans for SQL commands with signature
REM matching the one for SQL Text below.
REM Review SQL Text and adjust accordingly.
REM
REM PARAMETERS
REM None.
REM
REM EXAMPLE
REM SQL> START coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql;
REM
REM NOTES
REM 1. Should be run as SYSTEM or SYSDBA.
REM 2. User must have CREATE ANY SQL PROFILE privilege.
REM 3. SOURCE and TARGET systems can be the same or similar.
REM 4. To drop this custom SQL Profile after it has been created:
REM EXEC DBMS_SQLTUNE.DROP_SQL_PROFILE('coe_dagpvm5f8yq2t_1838229974');
REM 5. Be aware that using DBMS_SQLTUNE requires a license
REM for the Oracle Tuning Pack.
REM
WHENEVER SQLERROR EXIT SQL.SQLCODE;
REM
VAR signature NUMBER;
REM
DECLARE
sql_txt CLOB;
h SYS.SQLPROF_ATTR;
BEGIN
sql_txt := q'[
select /*+ coe_xfr_sql_profile */ t1.*,
t2.owner from t1,
t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id
]';
h := SYS.SQLPROF_ATTR(
q'[BEGIN_OUTLINE_DATA]',
q'[IGNORE_OPTIM_EMBEDDED_HINTS]',
q'[OPTIMIZER_FEATURES_ENABLE('11.2.0.4')]',
q'[DB_VERSION('11.2.0.4')]',
q'[ALL_ROWS]',
q'[OUTLINE_LEAF(@"SEL$1")]',
q'[FULL(@"SEL$1""T1"@"SEL$1")]',
q'[FULL(@"SEL$1""T2"@"SEL$1")]',
q'[LEADING(@"SEL$1""T1"@"SEL$1" "T2"@"SEL$1")]',
q'[USE_HASH(@"SEL$1""T2"@"SEL$1")]',
q'[END_OUTLINE_DATA]');
:signature :=DBMS_SQLTUNE.SQLTEXT_TO_SIGNATURE(sql_txt);
DBMS_SQLTUNE.IMPORT_SQL_PROFILE (
sql_text => sql_txt,
profile => h,
name => 'coe_dagpvm5f8yq2t_1838229974',
description => 'coe dagpvm5f8yq2t1838229974 '||:signature||'',
category => 'DEFAULT',
validate => TRUE,
replace => TRUE,
force_match => FALSE /* TRUE:FORCE (match even when differentliterals in SQL). FALSE:EXACT (similar to CURSOR_SHARING) */ );
END;
/
WHENEVER SQLERROR CONTINUE
SET ECHO OFF;
PRINT signature
PRO
PRO ... manual custom SQL Profile hasbeen created
PRO
SET TERM ON ECHO OFF LIN 80 TRIMS OFFNUMF "";
SPO OFF;
PRO
PROCOE_XFR_SQL_PROFILE_dagpvm5f8yq2t_1838229974 completed
7、修改coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql文件
修改上述第6步的红字部分,使之T2表走索引扫描。修改的内容如下(上述第2步的PLAN_TABLE_OUTPUT红字内容)
[oracle@oracle11g ~]$ vi coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql
SPOcoe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.log;
SET ECHO ON TERM ON LIN 2000 TRIMS ONNUMF 99999999999999999999;
REM
REM $Header: 215187.1coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql 11.4.3.5 2017/10/27carlos.sierra $
REM
REM Copyright (c) 2000-2011, OracleCorporation. All rights reserved.
REM
REM AUTHOR
REM
REM SCRIPT
REM coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql
REM
REM DESCRIPTION
REM This script is generated by coe_xfr_sql_profile.sql
REM It contains the SQL*Plus commands to create a custom
REM SQL Profile for SQL_ID dagpvm5f8yq2t based on plan hash
REM value 1838229974.
REM The custom SQL Profile to be created by this script
REM will affect plans for SQL commands with signature
REM matching the one for SQL Text below.
REM Review SQL Text and adjust accordingly.
REM
REM PARAMETERS
REM None.
REM
REM EXAMPLE
REM SQL> START coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql;
REM
REM NOTES
REM 1. Should be run as SYSTEM or SYSDBA.
REM 2. User must have CREATE ANY SQL PROFILE privilege.
REM 3. SOURCE and TARGET systems can be the same or similar.
REM 4. To drop this custom SQL Profile after it has been created:
REM EXEC DBMS_SQLTUNE.DROP_SQL_PROFILE('coe_dagpvm5f8yq2t_1838229974');
REM 5. Be aware that using DBMS_SQLTUNE requires a license
REM for the Oracle Tuning Pack.
REM
WHENEVER SQLERROR EXIT SQL.SQLCODE;
REM
VAR signature NUMBER;
REM
DECLARE
sql_txt CLOB;
h SYS.SQLPROF_ATTR;
BEGIN
sql_txt := q'[
select /*+ coe_xfr_sql_profile */ t1.*,
t2.owner from t1,
t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id
]';
h := SYS.SQLPROF_ATTR(
q'[BEGIN_OUTLINE_DATA]',
q'[IGNORE_OPTIM_EMBEDDED_HINTS]',
q'[OPTIMIZER_FEATURES_ENABLE('11.2.0.4')]',
q'[DB_VERSION('11.2.0.4')]',
q'[ALL_ROWS]',
q'[OUTLINE_LEAF(@"SEL$1")]',
q'[FULL(@"SEL$1""T1"@"SEL$1")]',
q'[INDEX(@"SEL$1""T2"@"SEL$1" ("T2"."OBJECT_ID"))]',
q'[LEADING(@"SEL$1""T1"@"SEL$1" "T2"@"SEL$1")]',
q'[USE_NL(@"SEL$1""T2"@"SEL$1")]',
q'[NLJ_BATCHING(@"SEL$1""T2"@"SEL$1")]',
q'[END_OUTLINE_DATA]');
:signature :=DBMS_SQLTUNE.SQLTEXT_TO_SIGNATURE(sql_txt);
DBMS_SQLTUNE.IMPORT_SQL_PROFILE (
sql_text => sql_txt,
profile => h,
name => 'SQLPROFILE_NAME2',
description => 'coe dagpvm5f8yq2t1838229974 '||:signature||'',
category => 'DEFAULT',
validate => TRUE,
replace => TRUE,
force_match => TRUE /* TRUE:FORCE (match even when different literalsin SQL). FALSE:EXACT (similar to CURSOR_SHARING) */ );
END;
/
WHENEVER SQLERROR CONTINUE
SET ECHO OFF;
PRINT signature
PRO
PRO ... manual custom SQL Profile hasbeen created
PRO
SET TERM ON ECHO OFF LIN 80 TRIMS OFFNUMF "";
SPO OFF;
PRO
PROCOE_XFR_SQL_PROFILE_dagpvm5f8yq2t_1838229974 completed
8、执行修改过的coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql文件
SQL>@/home/oracle/coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql SQL> REM SQL> REM $Header: 215187.1coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql 11.4.3.5 2017/10/27carlos.sierra $ SQL> REM SQL> REM Copyright (c) 2000-2011,Oracle Corporation. All rights reserved. SQL> REM SQL> REM AUTHOR SQL> REM [email protected] SQL> REM SQL> REM SCRIPT SQL> REM coe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql SQL> REM SQL> REM DESCRIPTION SQL> REM This script is generated bycoe_xfr_sql_profile.sql SQL> REM It contains the SQL*Plus commands to createa custom SQL> REM SQL Profile for SQL_ID dagpvm5f8yq2t basedon plan hash SQL> REM value 1838229974. SQL> REM The custom SQL Profile to be created by thisscript SQL> REM will affect plans for SQL commands withsignature SQL> REM matching the one for SQL Text below. SQL> REM Review SQL Text and adjust accordingly. SQL> REM SQL> REM PARAMETERS SQL> REM None. SQL> REM SQL> REM EXAMPLE SQL> REM SQL> STARTcoe_xfr_sql_profile_dagpvm5f8yq2t_1838229974.sql; SQL> REM SQL> REM NOTES SQL> REM 1. Should be run as SYSTEM or SYSDBA. SQL> REM 2. User must have CREATE ANY SQL PROFILEprivilege. SQL> REM 3. SOURCE and TARGET systems can be the sameor similar. SQL> REM 4. To drop this custom SQL Profile after ithas been created: SQL> REM EXECDBMS_SQLTUNE.DROP_SQL_PROFILE('coe_dagpvm5f8yq2t_1838229974'); SQL> REM 5. Be aware that using DBMS_SQLTUNE requiresa license SQL> REM for the Oracle Tuning Pack. SQL> REM SQL> WHENEVER SQLERROR EXITSQL.SQLCODE; SQL> REM SQL> VAR signature NUMBER; SQL> REM SQL> DECLARE 2 sql_txt CLOB; 3 h SYS.SQLPROF_ATTR; 4 BEGIN 5 sql_txt := q'[ 6 select /*+ coe_xfr_sql_profile*/ t1.*, 7 t2.owner from t1, 8 t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id 9 ]'; 10 h :=SYS.SQLPROF_ATTR( 11 q'[BEGIN_OUTLINE_DATA]', 12 q'[IGNORE_OPTIM_EMBEDDED_HINTS]', 13 q'[OPTIMIZER_FEATURES_ENABLE('11.2.0.4')]', 14 q'[DB_VERSION('11.2.0.4')]', 15 q'[ALL_ROWS]', 16 q'[OUTLINE_LEAF(@"SEL$1")]', 17 q'[FULL(@"SEL$1" "T1"@"SEL$1")]', 18 q'[INDEX(@"SEL$1" "T2"@"SEL$1"("T2"."OBJECT_ID"))]', 19 q'[LEADING(@"SEL$1" "T1"@"SEL$1""T2"@"SEL$1")]', 20 q'[USE_NL(@"SEL$1" "T2"@"SEL$1")]', 21 q'[NLJ_BATCHING(@"SEL$1" "T2"@"SEL$1")]', 22 q'[END_OUTLINE_DATA]'); 23 :signature := DBMS_SQLTUNE.SQLTEXT_TO_SIGNATURE(sql_txt); 24 DBMS_SQLTUNE.IMPORT_SQL_PROFILE ( 25 sql_text => sql_txt, 26 profile => h, 27 name =>'SQLPROFILE_NAME2', 28 description => 'coe dagpvm5f8yq2t 1838229974 '||:signature||'', 29 category => 'DEFAULT', 30 validate => TRUE, 31 replace => TRUE, 32 force_match => TRUE /* TRUE:FORCE (match even when different literalsin SQL). FALSE:EXACT (similar to CURSOR_SHARING) */ ); 33 END; 34 / PL/SQL procedure successfully completed. SQL> WHENEVER SQLERROR CONTINUE SQL> SET ECHO OFF; SIGNATURE --------------------- 9408953337440952030 ... manual custom SQL Profile has beencreated COE_XFR_SQL_PROFILE_dagpvm5f8yq2t_1838229974completed
9、查看带有/*+ coe_xfr_sql_profile */ hint的语句的执行计划, 已改变为index range scan+nested loop
SQL> select /*+ coe_xfr_sql_profile */ t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id; 41 rows selected. SQL> select * fromtable(dbms_xplan.display_cursor(null,null,'outline')); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- SQL_ID 7ubcv0ajyxb5x, child number 0 ------------------------------------- select /*+ coe_xfr_sql_profile */t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%' and t1.object_id=t2.object_id Plan hash value: 1022743391 -------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 1418 (100)| | | 1 | NESTED LOOPS | | 700 | 23100 | 1418 (1)| 00:00:18 | | 2 | NESTED LOOPS | | 700 | 23100 | 1418 (1)| 00:00:18 | |* 3 | TABLE ACCESS FULL | T1 | 700 | 16100 | 17 (0)| 00:00:01 | |* 4 | INDEX RANGE SCAN | T2_IDX | 1 | | 1 (0)| 00:00:01 | | 5 | TABLE ACCESS BY INDEX ROWID|T2 | 1 | 10 | 2 (0)| 00:00:01 | Outline Data ------------- /*+ BEGIN_OUTLINE_DATA IGNORE_OPTIM_EMBEDDED_HINTS OPTIMIZER_FEATURES_ENABLE('11.2.0.4') DB_VERSION('11.2.0.4') ALL_ROWS OUTLINE_LEAF(@"SEL$1") FULL(@"SEL$1" "T1"@"SEL$1") INDEX(@"SEL$1" "T2"@"SEL$1"("T2"."OBJECT_ID")) LEADING(@"SEL$1" "T1"@"SEL$1""T2"@"SEL$1") USE_NL(@"SEL$1" "T2"@"SEL$1") NLJ_BATCHING(@"SEL$1" "T2"@"SEL$1") END_OUTLINE_DATA */ Predicate Information (identified byoperation id): --------------------------------------------------- 3- filter(("T1"."OBJECT_NAME" LIKE '%T1%' AND"T1"."OBJECT_NAME" IS NOT NULL)) 4- access("T1"."OBJECT_ID"="T2"."OBJECT_ID") Note ----- - SQL profile SQLPROFILE_NAME2 used for this statement 41 rows selected.
七、SQL PROFILE的维护操作
1、禁用命令
begin
dbms_sqltune.alter_sql_profile(
name => 'SYS_SQLPROF_015f589bcf270000',
attribute_name =>'status',
value => 'disabled');
end;
/
2、启用命令
begin
dbms_sqltune.alter_sql_profile(
name => 'SYS_SQLPROF_015f589bcf270000',
attribute_name =>'status',
value => 'enabled');
end;
/
3、删除PROFILE
BEGIN
DBMS_SQLTUNE.DROP_SQL_PROFILE(name=>'SYS_SQLPROF_015f589bcf270000',);
END;
/
参考文章:
http://www.laoxiong.net/sql-profiles-part.html
http://www.laoxiong.net/sql-profiles-partii.html
http://www.itpub.net/thread-1919796-1-1.html