1. 程式人生 > >oracle 固定執行計劃(一)之 sql_profile

oracle 固定執行計劃(一)之 sql_profile

到oracle11G 時,已經有三種方式來固定執行計劃了

1.10G以前用的是儲存大綱

2.10G多了一種,sql_profile

3.11G又多了sql plan management

今天先講講sql_profile

1.先建立一張測試表,

SQL> create table emp as select * from scott.emp;

Table created.

2.選擇要固定執行計劃的sql語句

這裡選擇 select * from emp where empno=7521;

SQL> select * from emp where empno=7521;

     EMPNO ENAME			  JOB				     MGR HIREDATE		SAL	  COMM	   DEPTNO
---------- ------------------------------ --------------------------- ---------- --------------- ---------- ---------- ----------
      7521 WARD 			  SALESMAN			    7698 22-FEB-81	       1250	   500	       30


Execution Plan
----------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation	  | Name | Rows  | Bytes | Cost (%CPU)| Time	 |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	 |     1 |    87 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |    87 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("EMPNO"=7521)

Note
-----
   - dynamic sampling used for this statement (level=2)
可以看到這裡沒有建立索引,所以走的是全表掃描

3.查詢出sql的sql_id

SQL> select sql_id,sql_text from v$sql where sql_text like '%emp where empno%';

SQL_ID		     SQL_TEXT
-------------------- --------------------------------------------------
<span style="color:#ff6666;">9th5zrrtnxkjy</span>	     select * from emp where empno=7521

4.根據sql_id獲取 outline
---------------------------------------------------------------------------------------------------------------
SQL_ID	9th5zrrtnxkjy, child number 0
-------------------------------------
select * from emp where empno=7521

Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation	  | Name | Rows  | Bytes | Cost (%CPU)| Time	 |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	 |	 |	 |     2 (100)| 	 |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |    87 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

Outline Data
-------------

  /*+
      <span style="color:#ff0000;">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" "EMP"@"SEL$1")
      END_OUTLINE_DATA</span>
  */

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("EMPNO"=7521)

Note
-----
   - dynamic sampling used for this statement (level=2)


36 rows selected.
5.建立sql profile(SQLPROFILE_001)
SQL> declare 
   v_hints sys.sqlprof_attr; 
   begin 
   v_hints:=sys.sqlprof_attr( 
     'BEGIN_OUTLINE_DATA', 
     'IGNORE_OPTIM_EMBEDDED_HINTS', 
     'OPTIMIZER_FEATURES_ENABLE(''11.2.0.4'')', 
     'DB_VERSION(''11.2.0.4'')', 
     'ALL_ROWS', 
     'OUTL  2    3    4    5    6    7    8    9   10  INE_LEAF(@"SEL$1")',
     'FULL(@"SEL$1" "EMP"@"SEL$1")', 
     'END_OUTLINE_DATA'); 

   dbms_sqltune.import_sql_profile( 
     'select * from emp where empno=7521', 
     v_hints,'SQLPROFILE_001', 
     force_match=>true,replace=>false); 
  end; 
/ 11   12   13   14   15   16   17   18   19  

PL/SQL procedure successfully completed.

5.檢視是否使用sql profile
set autot trace explain 
select * from emp where empno=7521;
SQL> set autot trace explain 
select * from emp where empno=7521;SQL> 

Execution Plan
----------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation	  | Name | Rows  | Bytes | Cost (%CPU)| Time	 |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	 |     1 |    87 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |    87 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("EMPNO"=7521)

Note
-----
   - SQL profile "<span style="color:#ff0000;">SQLPROFILE_001</span>" used for this statement
可以看到,已經使用了sql_profile

6.在表字段empno上建立索引,再執行SQL看看執行計劃是否有變化

SQL> create index idx_empno on emp(empno);

Index created.

SQL> select * from emp where empno=7521;

Execution Plan
----------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation	  | Name | Rows  | Bytes | Cost (%CPU)| Time	 |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	 |     1 |    87 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |    87 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("EMPNO"=7521)

Note
-----
   - SQL profile "SQLPROFILE_001" used for this statement
從上圖可以看到,執行計劃仍然使用的是sql_profile中的執行計劃

7.刪除sql_profile再看看執行計劃是否有變化(按照最優計劃來說,應該會走index的)

刪除sql_profile 

SQL> BEGIN 
  DBMS_SQLTUNE.DROP_SQL_PROFILE(name => 'SQLPROFILE_001'); 
END; 
/  2    3    4  

PL/SQL procedure successfully completed.

SQL> select * from emp where empno=7522;

Execution Plan
----------------------------------------------------------
Plan hash value: 2426388914

-----------------------------------------------------------------------------------------
| Id  | Operation		    | Name	| Rows	| Bytes | Cost (%CPU)| Time	|
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	    |		|     1 |    87 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP	|     1 |    87 |     1   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN	    | IDX_EMPNO |     1 |	|     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("EMPNO"=7522)

Note
-----
   - dynamic sampling used for this statement (level=2)

果然,執行計劃改變了,這次SQL走的是index了.