SQL执行效率突然的衰减往往是因为目标SQL执行计划的改变。
一般情况下可以有如下方法来稳定执行计划
1、使用SQL PROFILE
2、使用SPM
而SQL PROFILE又分为自动类型的SQL PROFILE和手动类型SQL PROFLIE
1、使用自动类型的SQL PROFILE来稳定执行计划
环境准备:
SCOTT@TNS_PDB01>create table t1(n number);
Table created.
declare
begin
for i in 1 .. 10000 loop
insert into t1 values(i);
end loop;
commit;
end;
/
SCOTT@TNS_PDB01>select count(*) from t1;
COUNT(*)
----------
10000
SCOTT@TNS_PDB01>create index idx_t1 on t1(n);
Index created.
SCOTT@TNS_PDB01>exec dbms_stats.gather_table_stats(ownname => 'SCOTT',tabname => 'T1',estimate_percent => 100,method_opt => 'FOR ALL COLUMNS SIZE 1',cascade => true, no_invalidate => false);
PL/SQL procedure successfully completed.
SCOTT@TNS_PDB01>select /*+ no_index(t1 idx_t1) */* from t1 where n = 1;
N
----------
1
SCOTT@TNS_PDB01>select sql_text,sql_id,version_count,executions from v$sqlarea where sql_text like 'select /*+ no_index(t1 idx_t1) */* from t1 where n = 1%';
SQL_TEXT SQL_ID VERSION_COUNT EXECUTIONS
------------------------------------------------------------ ------------- --------
select /*+ no_index(t1 idx_t1) */* from t1 where n = 1 dc4r0cyrd3fx0 1 1
SCOTT@TNS_PDB01>select * from table(dbms_xplan.display_cursor(sql_id => 'dc4r0cyrd3fx0',cursor_child_no => 0,format => 'advanced'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------
SQL_ID dc4r0cyrd3fx0, child number 0
-------------------------------------
An uncaught error happened in prepare_sql_statement : ORA-01403: no data found
Plan hash value: 3617692013
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 7 (100)| |
|* 1 | TABLE ACCESS FULL| T1 | 1 | 4 | 7 (0)| 00:00:01 |
--------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T1@SEL$1
Outline Data
-------------
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('19.1.0')
DB_VERSION('19.1.0')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
FULL(@"SEL$1" "T1"@"SEL$1")
END_OUTLINE_DATA
*/
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("N"=1)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "N"[NUMBER,22]
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 1
---------------------------------------------------------------------------
1 - SEL$1 / T1@SEL$1
- no_index(t1 idx_t1)
Query Block Registry:
---------------------
<q o="2" f="y"><n><![CDATA[SEL$1]]></n><f><h><t><![CDATA[T1]]></t><s><![
CDATA[SEL$1]]></s></h></f></q>
56 rows selected.
使用DBMS_SQLTUNE包中CREATE_TUNING_TASK方法来自动调整执行计划
declare
lv_tuning_task_result varchar2(4000);
lv_sql_text CLOB := 'select /*+ no_index(t1 idx_t1) */* from t1 where n = 1';
lv_task_t1 varchar2(30) := 'tuning_task_t1';
begin
lv_tuning_task_result := dbms_sqltune.create_tuning_task(
sql_text => lv_sql_text,
user_name => 'SCOTT',
time_limit => 60,
scope => 'COMPREHENSIVE',
task_name => lv_task_t1,
description => 'task on t1');
end;
/
PL/SQL procedure successfully completed.
执行调优任务
SCOTT@TNS_PDB01>exec dbms_sqltune.execute_tuning_task(task_name => 'tuning_task_t1');
PL/SQL procedure successfully completed.
查看任务报告
SCOTT@TNS_PDB01>select dbms_sqltune.report_tuning_task(task_name => 'tuning_task_t1') from dual;
DBMS_SQLTUNE.REPORT_TUNING_TASK(TASK_NAME=>'TUNING_TASK_T1')
--------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
----------------------------------------------------
---------------------------
Tuning Task Name : tuning_task_t1
Tuning Task Owner : SCOTT
Workload Type : Single SQL Statement
Scope : COMPREHENSIVE
Time Limit(seconds): 60
Completion Status : COMPLETED
Started at : 01/13/2020 12:26:34
Completed at : 01/13/2020 12:26:35
------------------------------------------------------
-------------------------
Schema Name : SCOTT
Container Name: PDB01
SQL ID : dc4r0cyrd3fx0
SQL Text : select /*+ no_index(t1 i
dx_t1) */* from t1 where n = 1
------------------------------------------------
-------------------------------
FINDINGS SECTION (1 finding)
-----------------------------------------------------------
--------------------
1- SQL Profile Finding (see explain plans section below)
-----------------------------------------
---------------
A potentially better execution plan was fo
und for this statement.
Recommendation (estimated benefit: 90.9%)
-----------------------------------------
- Consider accepting the recommended SQL prof
ile.
--查看给出的建议
execute dbms_sqltune.accept_sql_profile(task_name =
> 'tuning_task_t1',
task_owner => 'SCOTT', repla
ce => TRUE);
Validation results
------------------
The SQL profile was tested by executing bo
th its plan and the original plan
and measuring their respective execution sta
tistics. A plan may have been
only partially executed if the other could be ru
n to completion in less time.
Original Plan With SQ
L Profile % Improved
------------- ----------------
----------
Completion Status: COMPLETE
COMPLETE
Elapsed Time (s): .00009
.000008 91.11 %
CPU Time (s): .00009 .000008
91.11 %
User I/O Time (s): 0
0
Buffer Gets: 22
2 90.9 %
Physical Read Requests: 0
0
Physical Write Requests: 0 0
Physical Read Bytes: 0 0
Physical Write Bytes: 0 0
Rows Processed: 1
1
Fetches: 1
1
Executions: 1
1
Notes
-----
1. Statistics for the original plan were ave
raged over 10 executions.
2. Statistics for the SQL profile plan were averaged
over 10 executions.
----------------------------------------------------------
---------------------
EXPLAIN PLANS SECTION
--------------------------------------------------------
-----------------------
1- Original With Adjusted Cost
------------------------------
Plan hash value: 3617692013
--------------------------------------------
------------------------------
| Id | Operation | Name | Rows | Bytes
| Cost (%CPU)| Time |
------------------------------------------------------
--------------------
| 0 | SELECT STATEMENT | | 1 | 4 | 7
(0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| T1 | 1 |
4 | 7 (0)| 00:00:01 |
-------------------------------------------------
-------------------------
Predicate Information (identified by operation id):
----------------------------------------
-----------
1 - filter("N"=1)
Hint Report (identified by operation id / Q
uery Block Name / Object Alias):
Total hints for statement: 3 (U - Unused (3))
-----------------------------------------
----------------------------------
0 - STATEMENT
U - IGNORE_OPTIM_EMBEDDED_HINTS / h
int overridden by another in parent quer
y block
U - OPTIMIZER_FEATURES_ENABLE(default) / h
int overridden by another in parent quer
y block
1 - SEL$1 / T1@SEL$1
U - no_index(t1 idx_t1) / rejected
by IGNORE_OPTIM_EMBEDDED_HINTS
2- Using SQL Profile
--------------------
Plan hash value: 1369807930
---------------------------------------------------------
------------------
| Id | Operation | Name | Rows
| Bytes | Cost (%CPU)| Time |
---------------------------------------------
------------------------------
| 0 | SELECT STATEMENT | | 1 | 4
| 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| IDX_T1 | 1 | 4 |
1 (0)| 00:00:01 |
---------------------------------------------------------
------------------
Predicate Information (identified by operation id):
-----------------------------------------------
----
1 - access("N"=1)
Hint Report (identified by operation id / Query Bl
ock Name / Object Alias):
Total hints for statement: 1 (U - Unused (1))
------------------------------------------------
---------------------------
1 - SEL$1 / T1@SEL$1
U - no_index(t1 idx_t1) / rejected
by IGNORE_OPTIM_EMBEDDED_HINTS
------------------------------------------------
-------------------------------
执行给出的建议
SCOTT@TNS_PDB01> execute dbms_sqltune.accept_sql_profile(task_name =>'tuning_task_t1',task_owner => 'SCOTT', replace => TRUE);
PL/SQL procedure successfully completed.
测试
SCOTT@TNS_PDB01>select /*+ no_index(t1 idx_t1) */* from t1 where n = 1;
N
----------
1
SCOTT@TNS_PDB01>select * from table(dbms_xplan.display_cursor(sql_id => null,cursor_child_no => null,format => 'advanced'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------
SQL_ID dc4r0cyrd3fx0, child number 0
-------------------------------------
An uncaught error happened in prepare_sql_statement : ORA-01403: no data found
Plan hash value: 1369807930
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1 (100)| |
|* 1 | INDEX RANGE SCAN| IDX_T1 | 1 | 4 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T1@SEL$1
Outline Data
-------------
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('19.1.0')
DB_VERSION('19.1.0')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
INDEX(@"SEL$1" "T1"@"SEL$1" ("T1"."N"))
END_OUTLINE_DATA
*/
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("N"=1)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "N"[NUMBER,22]
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 3 (U - Unused (1))
---------------------------------------------------------------------------
0 - STATEMENT
- IGNORE_OPTIM_EMBEDDED_HINTS
- OPTIMIZER_FEATURES_ENABLE(default)
1 - SEL$1 / T1@SEL$1
U - no_index(t1 idx_t1) / rejected by IGNORE_OPTIM_EMBEDDED_HINTS
Note
-----
- SQL profile SYS_SQLPROF_016f9d28a5520002 used for this statement
Query Block Registry:
---------------------
<q o="2" f="y"><n><![CDATA[SEL$1]]></n><f><h><t><![CDATA[T1]]></t><s><![
CDATA[SEL$1]]></s></h></f></q>
64 rows selected.
**但是当改变谓词条件的值时,执行计划还是走的全表扫描**
SCOTT@TNS_PDB01>select /*+ no_index(t1 idx_t1) */* from t1 where n = 2;
N
----------
2
SCOTT@TNS_PDB01>select * from table(dbms_xplan.display_cursor(sql_id => null,cursor_child_no => null,format => 'advanced'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------
SQL_ID bvwvfd5nnk9dq, child number 0
-------------------------------------
select /*+ no_index(t1 idx_t1) */* from t1 where n = 2
Plan hash value: 3617692013
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 7 (100)| |
|* 1 | TABLE ACCESS FULL| T1 | 1 | 4 | 7 (0)| 00:00:01 |
--------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T1@SEL$1
Outline Data
-------------
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('19.1.0')
DB_VERSION('19.1.0')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
FULL(@"SEL$1" "T1"@"SEL$1")
END_OUTLINE_DATA
*/
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("N"=2)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "N"[NUMBER,22]
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 1
---------------------------------------------------------------------------
1 - SEL$1 / T1@SEL$1
- no_index(t1 idx_t1)
Query Block Registry:
---------------------
<q o="2" f="y"><n><![CDATA[SEL$1]]></n><f><h><t><![CDATA[T1]]></t><s><![
CDATA[SEL$1]]></s></h></f></q>
56 rows selected.
**调整系统给的建议加上force_match => true,强制匹配**
SCOTT@TNS_PDB01> execute dbms_sqltune.accept_sql_profile(task_name =>'tuning_task_t1',task_owner => 'SCOTT', replace => TRUE,force_match => true);
PL/SQL procedure successfully completed.
SCOTT@TNS_PDB01>select /*+ no_index(t1 idx_t1) */* from t1 where n = 2;
N
----------
2
SCOTT@TNS_PDB01>select * from table(dbms_xplan.display_cursor(sql_id => null,cursor_child_no => null,format => 'advanced'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------
SQL_ID bvwvfd5nnk9dq, child number 1
-------------------------------------
An uncaught error happened in prepare_sql_statement : ORA-01403: no data found
Plan hash value: 1369807930
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1 (100)| |
|* 1 | INDEX RANGE SCAN| IDX_T1 | 1 | 4 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T1@SEL$1
Outline Data
-------------
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('19.1.0')
DB_VERSION('19.1.0')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
INDEX(@"SEL$1" "T1"@"SEL$1" ("T1"."N"))
END_OUTLINE_DATA
*/
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("N"=2)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "N"[NUMBER,22]
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 3 (U - Unused (1))
---------------------------------------------------------------------------
0 - STATEMENT
- IGNORE_OPTIM_EMBEDDED_HINTS
- OPTIMIZER_FEATURES_ENABLE(default)
1 - SEL$1 / T1@SEL$1
U - no_index(t1 idx_t1) / rejected by IGNORE_OPTIM_EMBEDDED_HINTS
Note
-----
- SQL profile SYS_SQLPROF_016f9d29d9d20003 used for this statement
Query Block Registry:
---------------------
<q o="2" f="y"><n><![CDATA[SEL$1]]></n><f><h><t><![CDATA[T1]]></t><s><![
CDATA[SEL$1]]></s></h></f></q>
64 rows selected.
SCOTT@TNS_PDB01>
SCOTT@TNS_PDB01>
SCOTT@TNS_PDB01>select /*+ no_index(t1 idx_t1) */* from t1 where n = 3;
N
----------
3
SCOTT@TNS_PDB01>select * from table(dbms_xplan.display_cursor(sql_id => null,cursor_child_no => null,format => 'advanced'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------
SQL_ID bvjnppfwsg57p, child number 0
-------------------------------------
select /*+ no_index(t1 idx_t1) */* from t1 where n = 3
Plan hash value: 1369807930
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1 (100)| |
|* 1 | INDEX RANGE SCAN| IDX_T1 | 1 | 4 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T1@SEL$1
Outline Data
-------------
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('19.1.0')
DB_VERSION('19.1.0')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
INDEX(@"SEL$1" "T1"@"SEL$1" ("T1"."N"))
END_OUTLINE_DATA
*/
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("N"=3)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "N"[NUMBER,22]
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 3 (U - Unused (1))
---------------------------------------------------------------------------
0 - STATEMENT
- IGNORE_OPTIM_EMBEDDED_HINTS
- OPTIMIZER_FEATURES_ENABLE(default)
1 - SEL$1 / T1@SEL$1
U - no_index(t1 idx_t1) / rejected by IGNORE_OPTIM_EMBEDDED_HINTS
Note
-----
- SQL profile SYS_SQLPROF_016f9d29d9d20003 used for this statement
Query Block Registry:
---------------------
<q o="2" f="y"><n><![CDATA[SEL$1]]></n><f><h><t><![CDATA[T1]]></t><s><![
CDATA[SEL$1]]></s></h></f></q>
64 rows selected.
SCOTT@TNS_PDB01>select /*+ no_index(t1 idx_t1) */* from t1 where n = 5;
N
----------
5
SCOTT@TNS_PDB01>select * from table(dbms_xplan.display_cursor(sql_id => null,cursor_child_no => null,format => 'advanced'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------
SQL_ID 6km0nbhw11mvq, child number 0
-------------------------------------
select /*+ no_index(t1 idx_t1) */* from t1 where n = 5
Plan hash value: 1369807930
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 1 (100)| |
|* 1 | INDEX RANGE SCAN| IDX_T1 | 1 | 4 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1 / T1@SEL$1
Outline Data
-------------
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('19.1.0')
DB_VERSION('19.1.0')
ALL_ROWS
OUTLINE_LEAF(@"SEL$1")
INDEX(@"SEL$1" "T1"@"SEL$1" ("T1"."N"))
END_OUTLINE_DATA
*/
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("N"=5)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "N"[NUMBER,22]
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 3 (U - Unused (1))
---------------------------------------------------------------------------
0 - STATEMENT
- IGNORE_OPTIM_EMBEDDED_HINTS
- OPTIMIZER_FEATURES_ENABLE(default)
1 - SEL$1 / T1@SEL$1
U - no_index(t1 idx_t1) / rejected by IGNORE_OPTIM_EMBEDDED_HINTS
Note
-----
- SQL profile SYS_SQLPROF_016f9d29d9d20003 used for this statement
Query Block Registry:
---------------------
<q o="2" f="y"><n><![CDATA[SEL$1]]></n><f><h><t><![CDATA[T1]]></t><s><![
CDATA[SEL$1]]></s></h></f></q>
64 rows selected.
可以看出在改变谓词条件后,还是走的索引。