oracle 固定執行計劃(一)之 sql_profile
阿新 • • 發佈:2019-01-29
到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
5.建立sql profile(SQLPROFILE_001)--------------------------------------------------------------------------------------------------------------- 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.
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了.