Oracle执行计划的稳定(使用自动类型的SQL PROFILE)

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.

可以看出在改变谓词条件后,还是走的索引。
发布了6 篇原创文章 · 获赞 6 · 访问量 391

猜你喜欢

转载自blog.csdn.net/u011285708/article/details/103955615