固定(穩定)執行計劃
你的應用的功能時快時慢,變化比較大,功能的性能能夠保持一種穩定的狀態,ORACLE 固定執行計劃,采用以下這幾種方式
oracle 10g采用 sql profile :兩種模式
提供腳本
create_sql_profile
提供綁定shared pool中已有的執行計劃中,找一個綁定或自己構造一個綁定

CREATE_SQL_PROFILE_AWR
綁定AWR中歷史的計劃中其他一個

sql_profile_hints
顯示sql profile中的HINT信息

一個SQL存在多個執行計劃,選擇其中一個固定
select * from scott.emp where deptno=30
select * from table(dbms_xplan.display_cursor('4hpk08j31nm7y',null))
SQL_ID 4hpk08j31nm7y, child number 0
-------------------------------------
select * from scott.emp where deptno=30
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100)| |
|* 1 | TABLE ACCESS FULL| EMP | 6 | 228 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DEPTNO"=30)
SQL_ID 4hpk08j31nm7y, child number 2
-------------------------------------
select * from scott.emp where deptno=30
Plan hash value: 1404472509
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 6 | 228 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | INDEX_EMP_DEPTNO | 6 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPTNO"=30)
語句綁定第一個子游標為固定的執行計劃:全表掃描
sys@GULL> @create_sql_profile
Enter value for sql_id: 4hpk08j31nm7y
Enter value for child_no (0): 0
Enter value for new_sql_id: 4hpk08j31nm7y
Enter value for profile_name (PROF_sqlid_planhash):
Enter value for category (DEFAULT):
Enter value for force_matching (TRUE):
原值 19: sql_id = '&&sql_id'
新值 19: sql_id = '4hpk08j31nm7y'
原值 20: and child_number = &&child_no
新值 20: and child_number = 0
原值 27: decode('&&profile_name','X0X0X0X0','PROF_&&sql_id'||'_'||plan_hash_value,'&&profile_name')
新值 27: decode('X0X0X0X0','X0X0X0X0','PROF_4hpk08j31nm7y'||'_'||plan_hash_value,'X0X0X0X0')
原值 33: sql_id = '&&new_sql_id';
新值 33: sql_id = '4hpk08j31nm7y';
原值 38: category => '&&category',
新值 38: category => 'DEFAULT',
原值 40: force_match => &&force_matching
新值 40: force_match => TRUE
原值 51: dbms_output.put_line('ERROR: sql_id: '||'&&sql_id'||' Child: '||'&&child_no'||' not found in v$sql.');
新值 51: dbms_output.put_line('ERROR: sql_id: '||'4hpk08j31nm7y'||' Child: '||'0'||' not found in v$sql.');
原值 52: dbms_output.put_line('ERROR: sql_id: '||'&&new_sql_id'||' not found in v$sqlarea.');
新值 52: dbms_output.put_line('ERROR: sql_id: '||'4hpk08j31nm7y'||' not found in v$sqlarea.');
SQL Profile PROF_4hpk08j31nm7y_1404472509 created.
執行相同的SQL語句運行
select * from scott.emp where deptno=30
select * from table(dbms_xplan.display_cursor('4hpk08j31nm7y',null))
SQL_ID 4hpk08j31nm7y, child number 0
-------------------------------------
select * from scott.emp where deptno=30
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100)| |
|* 1 | TABLE ACCESS FULL| EMP | 6 | 228 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DEPTNO"=30)
Note
-----
- SQL profile PROF_4hpk08j31nm7y_1404472509 used for this statement
在Note信息中可以看到sql profile的信息, - SQL profile PROF_4hpk08j31nm7y_1404472509 used for this statement,說明已經強制使用了手工綁定的執行計劃,之後這個語句就一直采用全表掃描了,不會再走索引的訪問方式
shared pool中之前沒有合適的執行計劃,你可以在awr(DBMS_XPLAN.DISPLAY_AWR)中查找歷史的執行計劃,查詢到了,采用create_sql_profile_awr這個過程來綁定
構造一個SQL語句兩個執行計劃,保存到AWR中
select * from scott.emp where deptno=30
select * from table(dbms_xplan.display_cursor('4hpk08j31nm7y',null))
alter session set optimizer_index_cost_adj=500
select * from scott.emp where deptno=30
select * from table(dbms_xplan.display_cursor('4hpk08j31nm7y',null))
execute DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT();
查看AWR中的執行計劃
select * from table(dbms_xplan.display_cursor('4hpk08j31nm7y',null))
SQL_ID 4hpk08j31nm7y
--------------------
select * from scott.emp where deptno=30
Plan hash value: 1404472509
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 6 | 522 | 2 (0)| 00:00:01 |
| 2 | INDEX RANGE SCAN | INDEX_EMP_DEPTNO | 6 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
SQL_ID 4hpk08j31nm7y
--------------------
select * from scott.emp where deptno=30
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100)| |
| 1 | TABLE ACCESS FULL| EMP | 6 | 522 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
使SQL語句固定走索引的處理模式
SQL> set serveroutput on
SQL> @create_sql_profile_awr.sql
Enter value for sql_id: 4hpk08j31nm7y
Enter value for plan_hash_value: 1404472509
Enter value for profile_name (PROF_sqlid_planhash):
Enter value for category (DEFAULT):
Enter value for force_matching (FALSE): TRUE
原值 19: sql_id = '&&sql_id'
新值 19: sql_id = '4hpk08j31nm7y'
原值 20: and plan_hash_value = &&plan_hash_value
新值 20: and plan_hash_value = 1404472509
原值 27: decode('&&profile_name','X0X0X0X0','PROF_&&sql_id'||'_'||'&&plan_hash_value','&&profile_name')
新值 27: decode('X0X0X0X0','X0X0X0X0','PROF_4hpk08j31nm7y'||'_'||'1404472509','X0X0X0X0')
原值 33: sql_id = '&&sql_id';
新值 33: sql_id = '4hpk08j31nm7y';
原值 38: category => '&&category',
新值 38: category => 'DEFAULT',
原值 40: force_match => &&force_matching
新值 40: force_match => TRUE
原值 51: dbms_output.put_line('ERROR: sql_id: '||'&&sql_id'||' Plan: '||'&&plan_hash_value'||' not found in AWR.');
新值 51: dbms_output.put_line('ERROR: sql_id: '||'4hpk08j31nm7y'||' Plan: '||'1404472509'||' not found in AWR.');
SQL Profile PROF_4hpk08j31nm7y_1404472509 create
重新執行SQL語句並查看執行計劃
select * from scott.emp where deptno=30
select * from table(dbms_xplan.display_cursor(null,null))
SQL_ID 4hpk08j31nm7y, child number 0
-------------------------------------
select * from scott.emp where deptno=30
Plan hash value: 1404472509
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 4 | 348 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | INDEX_EMP_DEPTNO | 2 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPTNO"=30)
Note
-----
- SQL profile PROF_4hpk08j31nm7y_1404472509 used for this statement
note 信息中已經使用了sql profile,而且語句也是走索引
shared pool和awr中沒有一個合適的,需要自己構造這個sql語句的執行計劃,進行偷梁換柱
select * from scott.emp where deptno=30
select * from table(dbms_xplan.display_cursor('4hpk08j31nm7y',null))
SQL_ID 4hpk08j31nm7y, child number 0
-------------------------------------
select * from scott.emp where deptno=30
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100)| |
|* 1 | TABLE ACCESS FULL| EMP | 6 | 228 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DEPTNO"=30)
可以構造一個走deptno索引的,在走索引的執行計劃去替換全表
select /*+index(emp index_emp_deptno)*/ * from scott.emp where deptno=30
select * from table(dbms_xplan.display_cursor(null,null))
SQL_ID 2hdyvqk9b09va, child number 0
-------------------------------------
select /*+index(emp index_emp_deptno)*/ * from scott.emp where
deptno=30
Plan hash value: 1404472509
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 10 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 6 | 228 | 10 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | INDEX_EMP_DEPTNO | 6 | | 5 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPTNO"=30)
可以使用SQL_ID 2hdyvqk9b09va, child number 0,來替換之前SQL_ID 4hpk08j31nm7y, child number 0的執行計劃
sys@GULL> @create_sql_profile
Enter value for sql_id: 2hdyvqk9b09va
Enter value for child_no (0): 0
Enter value for new_sql_id: 4hpk08j31nm7y
Enter value for profile_name (PROF_sqlid_planhash):
Enter value for category (DEFAULT):
Enter value for force_matching (TRUE):
原值 19: sql_id = '&&sql_id'
新值 19: sql_id = '2hdyvqk9b09va'
原值 20: and child_number = &&child_no
新值 20: and child_number = 0
原值 27: decode('&&profile_name','X0X0X0X0','PROF_&&sql_id'||'_'||plan_hash_value,'&&profile_name')
新值 27: decode('X0X0X0X0','X0X0X0X0','PROF_2hdyvqk9b09va'||'_'||plan_hash_value,'X0X0X0X0')
原值 33: sql_id = '&&new_sql_id';
新值 33: sql_id = '4hpk08j31nm7y';
原值 38: category => '&&category',
新值 38: category => 'DEFAULT',
原值 40: force_match => &&force_matching
新值 40: force_match => TRUE
原值 51: dbms_output.put_line('ERROR: sql_id: '||'&&sql_id'||' Child: '||'&&child_no'||' not found in v$sql.');
新值 51: dbms_output.put_line('ERROR: sql_id: '||'2hdyvqk9b09va'||' Child: '||'0'||' not found in v$sql.');
原值 52: dbms_output.put_line('ERROR: sql_id: '||'&&new_sql_id'||' not found in v$sqlarea.');
新值 52: dbms_output.put_line('ERROR: sql_id: '||'4hpk08j31nm7y'||' not found in v$sqlarea.');
SQL Profile PROF_2hdyvqk9b09va_3956160932 created.
再次查看原始語句的執行計劃
select * from scott.emp where deptno=30
select * from table(dbms_xplan.display_cursor('4hpk08j31nm7y',null))
SQL_ID 4hpk08j31nm7y, child number 0
-------------------------------------
select * from scott.emp where deptno=30
Plan hash value: 1404472509
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 10 (100)| |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP | 6 | 228 | 10 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | INDEX_EMP_DEPTNO | 6 | | 5 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPTNO"=30)
Note
-----
- SQL profile PROF_2hdyvqk9b09va_3956160932 used for this statement
偷梁換柱完成,操作起來也是很方便。
SQL> @sql_profile_hints.sql
Enter value for profile_name: PROF_4hpk08j31nm7y_1404472509
原值 19: 'and name like (''&&profile_name'') '||
新值 19: 'and name like (''PROF_4hpk08j31nm7y_1404472509'') '||
原值 38: 'and p.name like (''&&profile_name'')) '||
新值 38: 'and p.name like (''PROF_4hpk08j31nm7y_1404472509'')) '||
HINT
--------------------------------------------------------------------------------
----------------------------------------------------------------------
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('11.2.0.3')
DB_VERSION('11.2.0.3')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
INDEX_RS_ASC(@"SEL$1" "EMP"@"SEL$1" ("EMP"."DEPTNO"))
6 rows selected.
下一篇講解一些用coe_xfr_sql_profile腳本去綁定執行計劃