- SQL Profiles介绍:
- SQL Profiles是在10g中被引进的新特性,主要是通过DBMS_SQLTUNE包或者EM来管理,它是AST(Automatic SQL Tuning)过程的一部分;也在10g版本中使用较多,11g中更多使用SPM;
- Automatic SQL Tuning:
- 因为缺少必要的信息,查询优化器对sql语句可能会产生不准确的评估(比如返回的记录数等),从而导致生成一个较差的执行计划;传统的处理方法是手动添加hints来改变执行计划,但是对于打包的应用程序,无法修改相应的sql语句,所以只能等应用程序提供商来解决这个问题;
- Automatic SQL Tuning使用SQL Profile的特性解决了这个问题;Automatic Tuning Optimizer会为每条sql语句创建一个包含辅助信息(主要通过动态采用和部分执行技术收集附加信息)的SQL Profile;查询优化器可以计算出更精确的cardinality/selectivity/cost的评估,从而生成更优的执行计划;
- 在产生SQL Profile期间,Automatic Tuning Optimizer也会为了与优化器参数匹配从而执行SQL语句的历史信息,比如把optimizer_mode参数从all_rows修改到first_rows;
- SQL Profile:
- SQL Profile是存储在数据字典中的一系列的信息(主要是包括在AST过程中针对较差执行计划的一些修正信息),它可以使查询优化器针对某条sql生成更优的执行计划;
- SQL Profile并不包含独立的执行计划,只是优化器在选择执行计划时除了参考数据库配置/绑定变量值/优化器统计信息/数据集等信息之外还会参考SQL Profile中的附加信息;
- 一段时间后,SQL Profile的内容可能会过期,需要运行AST重新生成SQL Profile;
- tips:SQL Profile并不会像Stored Outlines一样固定SQL语句的执行计划;即便拥有相同SQL Profile,由于表的增长或者索引的创建删除,执行计划也会改变;
- 如何控制SQL Profile的范围:
- SQL Profile的范围由category属性控制,它决定了哪些用户会话可以应用这些profile;
- 可以通过dba_sql_profiles字典来查看(SELECT NAME, category FROM dba_sql_profiles);
- 默认情况下,所有的profiles都属于DEFAULT分类,表示所有的初始化参数sqltune_category=DEFAULT(这也是默认值)的用户会话都可使用这些profile;
- 可以通过修改sqltune_category参数来控制profile使用的范围,从而可以在发布之前进行测试;
- 可以使用SQL Profile的语句:
- SELECT语句;
- UDPATE语句;
- INSERT INTO SELECT语句;
- DELETE语句;
- CTAS语句;
- MERGE语句(包含UPDATE或者INSERT操作);
- Sql Profiles是对OUTLINES的增强,并且具有自己的特点:
- SQL Profiles更容易生成,更改和控制;
- SQL Profiles对SQL语句的支持更广泛;
- 使用SQL Profiles的目的:
- 稳定或者”锁定”SQL的执行计划;
- 在不能修改应用程序中SQL的情况下,使SQL按照指定的执行计划运行;
- 管理SQL Profiles:
- 首先用户需要有CREATE ANY SQL_PROFILE, DROP ANY SQL_PROFILE, ALTER ANY SQL_PROFILE权限;
- 从STA优化结果中接受一个Profile:DBMS_SQLTUNE.ACCEPT_SQL_PROFILE (task_name,object_id,name,description,category,task_owner,replace,force_match,profile_type),例子<<如何使用SQL Tuning Advisor来生成SQL Profile,及SQL Profile原理>>;
- 修改Profile:DBMS_SQLTUNE.ALTER_SQL_PROFILE (name,attribute_name,value);
- 删除Profile:DBMS_SQLTUNE.DROP_SQL_PROFILE (name,ignore);
- SQL Profile的迁移,例子<<How to Move SQL Profiles from One Database to Another>>;
- 使用DBMS_SQLTUNE.IMPORT_SQL_PROFILE过程手工创建SQL Profiles,这种方法创建的SQL Profiles和Outlines一样,能够稳定SQL的执行计划,例子;
- 稳定现有的SQL的执行计划;
- 在不能修改SQL的情况下改变并固定SQL的执行计划,即使原来的SQL使用了hints;
BANNER
—————————————————————-
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 – Prod
PL/SQL Release 10.2.0.1.0 – Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 – Production
NLSRTL Version 10.2.0.1.0 – Production
CREATE TABLE t1 AS SELECT object_id, object_name FROM dba_objects WHERE rownum <= 50000;
CREATE TABLE t2 AS SELECT * FROM dba_objects;
CREATE INDEX idx_t2_oid ON t2(object_id);
BEGIN
dbms_stats.gather_table_stats(USER, ‘T1’, cascade => TRUE, method_opt => ‘for all columns size 1’);
dbms_stats.gather_table_stats(USER, ‘T2’, cascade => TRUE, method_opt => ‘for all columns size 1’);
END;
/
— 3.查看SQL的执行计划和统计信息,并选择不同的访问路径;
SQL> SET AUTOT ON;
SQL> SELECT t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE ‘%T1%’ AND t1.object_id = t2.object_id;
Execution Plan
———————————————————-
Plan hash value: 1838229974
—————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————
| 0 | SELECT STATEMENT | | 2500 | 97K| 212 (3)| 00:00:03 |
|* 1 | HASH JOIN | | 2500 | 97K| 212 (3)| 00:00:03 |
|* 2 | TABLE ACCESS FULL| T1 | 2500 | 72500 | 55 (4)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T2 | 50350 | 540K| 155 (2)| 00:00:02 |
—————————————————————————
Predicate Information (identified by operation id):
—————————————————
1 – access(“T1″.”OBJECT_ID”=”T2″.”OBJECT_ID”)
2 – filter(“T1″.”OBJECT_NAME” LIKE ‘%T1%’)
Statistics
———————————————————-
304 recursive calls
0 db block gets
974 consistent gets
0 physical reads
0 redo size
1402 bytes sent via SQL*Net to client
396 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
5 sorts (memory)
0 sorts (disk)
26 rows processed
26 rows selected.
Execution Plan
———————————————————-
Plan hash value: 1164754026
——————————————————————————–
———-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
Time |
——————————————————————————–
———-
| 0 | SELECT STATEMENT | | 2500 | 97K| 5061 (1)|
00:01:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)|
00:00:01 |
| 2 | NESTED LOOPS | | 2500 | 97K| 5061 (1)|
00:01:01 |
|* 3 | TABLE ACCESS FULL | T1 | 2500 | 72500 | 55 (4)|
00:00:01 |
|* 4 | INDEX RANGE SCAN | IDX_T2_OID | 1 | | 1 (0)|
00:00:01 |
——————————————————————————–
———-
Predicate Information (identified by operation id):
—————————————————
3 – filter(“T1″.”OBJECT_NAME” LIKE ‘%T1%’)
4 – access(“T1″.”OBJECT_ID”=”T2″.”OBJECT_ID”)
Statistics
———————————————————-
1 recursive calls
0 db block gets
288 consistent gets
0 physical reads
0 redo size
1402 bytes sent via SQL*Net to client
396 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
26 rows processed
~~~~~~~~~~~~
GENERAL INFORMATION SECTION
——————————————————————————-
Tuning Task Name : TASK_62
Tuning Task Owner : SYS
Scope : COMPREHENSIVE
Time Limit(seconds) : 1800
Completion Status : COMPLETED
Started at : 07/26/2014 10:45:03
Completed at : 07/26/2014 10:45:03
Number of SQL Profile Findings : 1
——————————————————————————-
Schema Name: SYS
SQL ID : cy6x06rhrt54x
SQL Text : SELECT t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE
‘%T1%’ AND t1.object_id = t2.object_id
——————————————————————————-
FINDINGS SECTION (1 finding)
——————————————————————————-
1- SQL Profile Finding (see explain plans section below)
——————————————————–
A potentially better execution plan was found for this statement.
Recommendation (estimated benefit: 49.32%)
——————————————
– Consider accepting the recommended SQL profile.
execute dbms_sqltune.accept_sql_profile(task_name => ‘TASK_62’, replace
=> TRUE);
——————————————————————————-
EXPLAIN PLANS SECTION
——————————————————————————-
1- Original With Adjusted Cost
——————————
Plan hash value: 1838229974
—————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————
| 0 | SELECT STATEMENT | | 26 | 1040 | 212 (3)| 00:00:03 |
|* 1 | HASH JOIN | | 26 | 1040 | 212 (3)| 00:00:03 |
|* 2 | TABLE ACCESS FULL| T1 | 26 | 754 | 55 (4)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T2 | 50350 | 540K| 155 (2)| 00:00:02 |
—————————————————————————
Predicate Information (identified by operation id):
—————————————————
1 – access(“T1″.”OBJECT_ID”=”T2″.”OBJECT_ID”)
2 – filter(“T1″.”OBJECT_NAME” LIKE ‘%T1%’)
2- Using SQL Profile
——————–
Plan hash value: 1164754026
——————————————————————————–
———-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
Time |
——————————————————————————–
———-
| 0 | SELECT STATEMENT | | 26 | 1040 | 107 (2)|
00:00:02 |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)|
00:00:01 |
| 2 | NESTED LOOPS | | 26 | 1040 | 107 (2)|
00:00:02 |
|* 3 | TABLE ACCESS FULL | T1 | 26 | 754 | 55 (4)|
00:00:01 |
|* 4 | INDEX RANGE SCAN | IDX_T2_OID | 1 | | 1 (0)|
00:00:01 |
——————————————————————————–
———-
Predicate Information (identified by operation id):
—————————————————
3 – filter(“T1″.”OBJECT_NAME” LIKE ‘%T1%’)
4 – access(“T1″.”OBJECT_ID”=”T2″.”OBJECT_ID”)
3.从结果发现STA找到了最优的执行计划,T1表上的条件过滤后的结果集记录数为26,非常准确,所以可以选择接受这个SQL Profile;
PL/SQL procedure successfully completed.
NAME CATEGORY SIGNATURE
—————————— —————————— ———-
SQL_TEXT
——————————————————————————–
SYS_SQLPROF_0151dc24f6338000 DEFAULT 8.9755E+18
SELECT t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE ‘%T1%’ AND t1.object
_id = t2.object_id
SIGNATURE CATEGORY ATTR# ATTR_VAL
———– ——– ———- ——————————————————————————–
Explained.
SQL> SELECT * FROM TABLE (DBMS_XPLAN.DISPLAY);
PLAN_TABLE_OUTPUT
——————————————————————————–
Plan hash value: 1838229974
—————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————
| 0 | SELECT STATEMENT | | 2600 | 101K| 401 (49)| 00:00:05 |
|* 1 | HASH JOIN | | 2600 | 101K| 401 (49)| 00:00:05 |
|* 2 | TABLE ACCESS FULL| T1 | 2600 | 75400 | 245 (79)| 00:00:03 |
| 3 | TABLE ACCESS FULL| T2 | 50350 | 540K| 155 (2)| 00:00:02 |
—————————————————————————
PLAN_TABLE_OUTPUT
——————————————————————————–
Predicate Information (identified by operation id):
—————————————————
1 – access(“T1″.”OBJECT_ID”=”T2″.”OBJECT_ID”)
2 – filter(“T1″.”OBJECT_NAME” LIKE ‘%T1%’)
Note
—–
– SQL profile “SYS_SQLPROF_0151dc24f6338000” used for this statement
BANNER
—————————————————————-
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 – Prod
PL/SQL Release 10.2.0.1.0 – Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 – Production
NLSRTL Version 10.2.0.1.0 – Production
BANNER
——————————————————————————–
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 – Production
PL/SQL Release 11.2.0.3.0 – Production
CORE 11.2.0.3.0 Production
TNS for Linux: Version 11.2.0.3.0 – Production
NLSRTL Version 11.2.0.3.0 – Production
SQL> ALTER USER hr IDENTIFIED BY oracle ACCOUNT UNLOCK;
SQL> conn hr/oracle
SQL> CREATE TABLE emp AS SELECT * FROM employees;
SQL> ALTER TABLE emp ADD CONSTRAINT PK_EMP_ID PRIMARY KEY (EMPLOYEE_ID) USING INDEX;
SQL> SET AUTOT ON
SQL> SELECT /*+ NO_INDEX(e pk_emp_id) */ employee_id, first_name FROM emp e WHERE employee_id=198;
EMPLOYEE_ID FIRST_NAME
———– ——————–
198 Donald
Execution Plan
———————————————————-
Plan hash value: 3956160932
————————————————————————–
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
————————————————————————–
| 0 | SELECT STATEMENT | | 4 | 100 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| EMP | 4 | 100 | 3 (0)| 00:00:01 |
————————————————————————–
Predicate Information (identified by operation id):
—————————————————
1 – filter(“EMPLOYEE_ID”=198)
Statistics
———————————————————-
0 recursive calls
0 db block gets
5 consistent gets
0 physical reads
0 redo size
482 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
my_sta_name VARCHAR2(30);
my_sqltext CLOB;
BEGIN
my_sqltext := ‘SELECT /*+ NO_INDEX(e pk_emp_id) */ employee_id, first_name FROM emp e WHERE employee_id=198’;
my_sta_name := dbms_sqltune.create_tuning_task(sql_text => my_sqltext,
user_name => ‘HR’,
scope => ‘COMPREHENSIVE’,
time_limit => 60,
task_name => ‘my_sql_tuning_task’);
dbms_sqltune.execute_tuning_task(task_name => my_sta_name);
dbms_sqltune.accept_sql_profile(task_name => my_sta_name, NAME => ‘my_sql_profile’);
END;
/
EMPLOYEE_ID FIRST_NAME
———– ——————–
198 Donald
Execution Plan
———————————————————-
Plan hash value: 2864363232
——————————————————————————–
———
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| T
ime |
——————————————————————————–
———
| 0 | SELECT STATEMENT | | 1 | 9 | 1 (0)| 0
0:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 9 | 1 (0)| 0
0:00:01 |
|* 2 | INDEX UNIQUE SCAN | PK_EMP_ID | 1 | | 0 (0)| 0
0:00:01 |
——————————————————————————–
———
Predicate Information (identified by operation id):
—————————————————
2 – access(“EMPLOYEE_ID”=198)
Note
—–
– SQL profile “my_sql_profile” used for this statement
Statistics
———————————————————-
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
482 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
dbms_sqltune.create_stgtab_sqlprof(table_name => ‘TB_SQLP_STAGE’, schema_name => ‘HR’);
dbms_sqltune.pack_stgtab_sqlprof(profile_name => ‘my_sql_profile’,
staging_table_name => ‘TB_SQLP_STAGE’,
staging_schema_owner => ‘HR’);
END;
/
Export: Release 10.2.0.1.0 – Production on Friday, 25 July, 2014 11:49:29
Copyright (c) 2003, 2005, Oracle. All rights reserved.
Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 – Production
With the Partitioning, OLAP and Data Mining options
Starting “HR”.”SYS_EXPORT_TABLE_01″: hr/******** directory=data_pump_dir dumpfile=sqlp.dmp tables=TB_SQLP_STAGE
Estimate in progress using BLOCKS method…
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 320 KB
Processing object type TABLE_EXPORT/TABLE/TABLE
. . exported “HR”.”TB_SQLP_STAGE” 9.257 KB 1 rows
Master table “HR”.”SYS_EXPORT_TABLE_01″ successfully loaded/unloaded
******************************************************************************
Dump file set for HR.SYS_EXPORT_TABLE_01 is:
/u01/app/oracle/admin/ORCL/dpdump/sqlp.dmp
Import: Release 11.2.0.3.0 – Production on Fri Jul 25 11:52:37 2014
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 – Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Master table “HR”.”SYS_IMPORT_TABLE_01″ successfully loaded/unloaded
Starting “HR”.”SYS_IMPORT_TABLE_01″: hr/******** directory=data_pump_dir dumpfile=sqlp.dmp tables=TB_SQLP_STAGE
Processing object type TABLE_EXPORT/TABLE/TABLE
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
. . imported “HR”.”TB_SQLP_STAGE” 9.257 KB 1 rows
Job “HR”.”SYS_IMPORT_TABLE_01″ successfully completed at 11:53:05
dbms_sqltune.unpack_stgtab_sqlprof(profile_name => ‘my_sql_profile’,
REPLACE => TRUE,
staging_table_name => ‘TB_SQLP_STAGE’,
staging_schema_owner => ‘HR’);
END;
/
EMPLOYEE_ID FIRST_NAME
———– ——————–
198 Donald
Execution Plan
———————————————————-
Plan hash value: 2864363232
——————————————————————————–
———
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| T
ime |
——————————————————————————–
———
| 0 | SELECT STATEMENT | | 1 | 9 | 1 (0)| 0
0:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 9 | 1 (0)| 0
0:00:01 |
|* 2 | INDEX UNIQUE SCAN | PK_EMP_ID | 1 | | 0 (0)| 0
0:00:01 |
——————————————————————————–
———
Predicate Information (identified by operation id):
—————————————————
2 – access(“EMPLOYEE_ID”=198)
Note
—–
– SQL profile “my_sql_profile” used for this statement
Statistics
———————————————————-
0 recursive calls
0 db block gets
5 consistent gets
0 physical reads
0 redo size
497 bytes sent via SQL*Net to client
419 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
BANNER
—————————————————————-
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 – Prod
PL/SQL Release 10.2.0.1.0 – Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 – Production
NLSRTL Version 10.2.0.1.0 – Production
Argument Name Type In/Out Default?
—————————— ———————– —— ——–
SQL_TEXT CLOB IN
PROFILE SQLPROF_ATTR IN
NAME VARCHAR2 IN DEFAULT
DESCRIPTION VARCHAR2 IN DEFAULT
CATEGORY VARCHAR2 IN DEFAULT
VALIDATE BOOLEAN IN DEFAULT
REPLACE BOOLEAN IN DEFAULT
FORCE_MATCH BOOLEAN IN DEFAULT
dbms_sqltune.drop_sql_profile(‘SYS_SQLPROF_0151dc24f6338000’);
END;
/
BEGIN
dbms_stats.set_table_stats(‘SYS’, ‘T1’, numrows => 5000);
END;
/
SQL_ID PLAN_HASH_VALUE
————- —————
SQL_TEXT
——————————————————————————–
cy6x06rhrt54x 1838229974
SELECT t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE ‘%T1%’ AND t1.object
_id = t2.object_id
PLAN_TABLE_OUTPUT
——————————————————————————–
SQL_ID cy6x06rhrt54x, child number 0
————————————-
SELECT t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE ‘%T1%’ AND
t1.object_id = t2.object_id
Plan hash value: 1838229974
—————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————
| 0 | SELECT STATEMENT | | | | 212 (100)| |
PLAN_TABLE_OUTPUT
——————————————————————————–
|* 1 | HASH JOIN | | 2500 | 97K| 212 (3)| 00:00:03 |
|* 2 | TABLE ACCESS FULL| T1 | 2500 | 72500 | 55 (4)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T2 | 50350 | 540K| 155 (2)| 00:00:02 |
—————————————————————————
Outline Data
————-
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE(‘10.2.0.1’)
ALL_ROWS
OUTLINE_LEAF(@”SEL$1″)
FULL(@”SEL$1″ “T1″@”SEL$1″)
FULL(@”SEL$1” “T2″@”SEL$1″)
LEADING(@”SEL$1” “T1″@”SEL$1” “T2″@”SEL$1″)
USE_HASH(@”SEL$1” “T2″@”SEL$1”)
END_OUTLINE_DATA
*/
Predicate Information (identified by operation id):
1 – access(“T1″.”OBJECT_ID”=”T2″.”OBJECT_ID”)
2 – filter(“T1″.”OBJECT_NAME” LIKE ‘%T1%’)
Parameter 1:
SQL_ID (required)
PLAN_HASH_VALUE AVG_ET_SECS
————— ———–
1838229974 .087
1164754026
Parameter 2:
PLAN_HASH_VALUE (required)
Values passed to coe_xfr_sql_profile:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SQL_ID : “cy6x06rhrt54x”
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. and PHV &&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_cy6x06rhrt54x_1838229974.sql
on TARGET system in order to create a custom SQL Profile
with plan 1838229974 linked to adjusted sql_text.
COE_XFR_SQL_PROFILE completed.
2 sql_txt CLOB;
3 h SYS.SQLPROF_ATTR;
4 PROCEDURE wa (p_line IN VARCHAR2) IS
5 BEGIN
6 DBMS_LOB.WRITEAPPEND(sql_txt, LENGTH(p_line), p_line);
7 END wa;
8 BEGIN
9 DBMS_LOB.CREATETEMPORARY(sql_txt, TRUE);
10 DBMS_LOB.OPEN(sql_txt, DBMS_LOB.LOB_READWRITE);
11 — SQL Text pieces below do not have to be of same length.
12 — So if you edit SQL Text (i.e. removing temporary Hints),
13 — there is no need to edit or re-align unmodified pieces.
14 wa(q'[SELECT t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE ‘%T1]’);
15 wa(q'[%’ AND t1.object_id = t2.object_id
16 ]’);
17 DBMS_LOB.CLOSE(sql_txt);
18 h := SYS.SQLPROF_ATTR(
19 q'[BEGIN_OUTLINE_DATA]’,
20 q'[IGNORE_OPTIM_EMBEDDED_HINTS]’,
21 q'[OPTIMIZER_FEATURES_ENABLE(‘10.2.0.1′)]’,
22 q'[ALL_ROWS]’,
23 q'[OUTLINE_LEAF(@”SEL$1″)]’,
24 q'[FULL(@”SEL$1″ “T1″@”SEL$1″)]’,
25 q'[FULL(@”SEL$1” “T2″@”SEL$1″)]’,
26 q'[LEADING(@”SEL$1” “T1″@”SEL$1” “T2″@”SEL$1″)]’,
27 q'[USE_HASH(@”SEL$1” “T2″@”SEL$1″)]’,
28 q'[END_OUTLINE_DATA]’);
29 :signature := DBMS_SQLTUNE.SQLTEXT_TO_SIGNATURE(sql_txt);
30 :signaturef := DBMS_SQLTUNE.SQLTEXT_TO_SIGNATURE(sql_txt, TRUE);
31 DBMS_SQLTUNE.IMPORT_SQL_PROFILE (
32 sql_text => sql_txt,
33 profile => h,
34 name => ‘coe_cy6x06rhrt54x_1838229974’,
35 description => ‘coe cy6x06rhrt54x 1838229974 ‘||:signature||’ ‘||:signaturef||”,
36 category => ‘DEFAULT’,
37 validate => TRUE,
38 replace => TRUE,
39 force_match => FALSE /* TRUE:FORCE (match even when different literals in SQL). FALSE:EXACT (similar to CURSOR_SHARING) */ );
40 DBMS_LOB.FREETEMPORARY(sql_txt);
41 END;
42 /
PL/SQL procedure successfully completed.
SQL>WHENEVER SQLERROR CONTINUE
SQL>SET ECHO OFF;
SIGNATURE
———————
8975541025552400288
SIGNATUREF
———————
3960696072677096522
… manual custom SQL Profile has been created
COE_XFR_SQL_PROFILE_cy6x06rhrt54x_1838229974 completed
2.INDEX RANGE SCAN + NESTED LOOP的方式:SELECT /*+ sql_profile index(t1) use_nl(t1 t2) */ t1.*, t2.owner FROM t1, t2 WHERE t1.object_name LIKE ‘%T1%’ AND t1.object_id = t2.object_id;
2 ;
SQL_ID PLAN_HASH_VALUE
————- —————
SQL_TEXT
——————————————————————————–
8cukn1u7dxssh 1838229974
SELECT /*+ sql_profile full(t1) full(t2) use_hash(t1 t2) */ t1.*, t2.owner FROM
t1, t2 WHERE t1.object_name LIKE ‘%T1%’ AND t1.object_id = t2.object_id
6csfwp8k7qu49 1164754026
SELECT /*+ sql_profile index(t1) use_nl(t1 t2) */ t1.*, t2.owner FROM t1, t2 WH
ERE t1.object_name LIKE ‘%T1%’ AND t1.object_id = t2.object_id
SQL>@/home/oracle/coe_xfr_sql_profile.sql 6csfwp8k7qu49 1164754026 — coe_xfr_sql_profile_6csfwp8k7qu49_1164754026.sql
q'[BEGIN_OUTLINE_DATA]’,
q'[IGNORE_OPTIM_EMBEDDED_HINTS]’,
q'[OPTIMIZER_FEATURES_ENABLE(‘10.2.0.1′)]’,
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'[END_OUTLINE_DATA]’);
Explained.
SQL>SELECT * FROM TABLE(dbms_xplan.display());
PLAN_TABLE_OUTPUT
——————————————————————————–
Plan hash value: 1164754026
——————————————————————————–
———-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
Time |
——————————————————————————–
———-
PLAN_TABLE_OUTPUT
——————————————————————————–
| 0 | SELECT STATEMENT | | 250 | 10000 | 554 (1)|
00:00:07 |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)|
00:00:01 |
| 2 | NESTED LOOPS | | 250 | 10000 | 554 (1)|
00:00:07 |
|* 3 | TABLE ACCESS FULL | T1 | 250 | 7250 | 53 (0)|
00:00:01 |
PLAN_TABLE_OUTPUT
——————————————————————————–
|* 4 | INDEX RANGE SCAN | IDX_T2_OID | 1 | | 1 (0)|
00:00:01 |
——————————————————————————–
———-
Predicate Information (identified by operation id):
—————————————————
PLAN_TABLE_OUTPUT
——————————————————————————–
3 – filter(“T1″.”OBJECT_NAME” LIKE ‘%T1%’)
4 – access(“T1″.”OBJECT_ID”=”T2″.”OBJECT_ID”)
Note
—–
– SQL profile “coe_8cukn1u7dxssh_1838229974” used for this statement
Explained.
SQL>SELECT * FROM TABLE(dbms_xplan.display());
PLAN_TABLE_OUTPUT
——————————————————————————–
Plan hash value: 1164754026
——————————————————————————–
———-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
Time |
——————————————————————————–
———-
PLAN_TABLE_OUTPUT
——————————————————————————–
| 0 | SELECT STATEMENT | | 250 | 10000 | 554 (1)|
00:00:07 |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)|
00:00:01 |
| 2 | NESTED LOOPS | | 250 | 10000 | 554 (1)|
00:00:07 |
|* 3 | TABLE ACCESS FULL | T1 | 250 | 7250 | 53 (0)|
00:00:01 |
PLAN_TABLE_OUTPUT
——————————————————————————–
|* 4 | INDEX RANGE SCAN | IDX_T2_OID | 1 | | 1 (0)|
00:00:01 |
——————————————————————————–
———-
Predicate Information (identified by operation id):
—————————————————
PLAN_TABLE_OUTPUT
——————————————————————————–
3 – filter(“T1″.”OBJECT_NAME” LIKE ‘%T2%’)
4 – access(“T1″.”OBJECT_ID”=”T2″.”OBJECT_ID”)
Note
—–
– SQL profile “coe_8cukn1u7dxssh_1838229974” used for this statement