驗證11g的adaptive cursor sharing功能
當oracle開啟繫結變數窺視功能,會在sql硬解析時窺探變數的實際值以求生成更為精確的執行計劃,但是若該列資料分佈極度不均,則可能適得其反,11g引入了adaptive cursor sharing.
查詢最佳化器會不斷做出調整以便不同的繫結變數各自獲取最優執行計劃,該功能系統預設開啟,無法手工禁止。
經此特性處理的sql需經歷三個階段: bind-sensitive -> bind-aware -> cursor merging
以下是11R2的原文解釋,對於原文的理解可能有偏差,還是直接看英文文件比較好;
Bind-sensitive cursor
A bind-sensitive cursor is a cursor whose optimal plan may depend on the value of a bind variable. The database monitors the behavior. of a bind-sensitive cursor that uses different bind values to determine whether a different plan is beneficial.
The criteria used by the optimizer to decide whether a cursor is bind-sensitive include the following:
· The optimizer has peeked at the bind values to generate selectivity estimates.
· A histogram exists on the column containing the bind value
Bind-aware cursor
When a statement with a bind-sensitive cursor executes, the database decides whether to mark the cursor bind-aware. The decision depends on whether the cursor produces significantly different data access patterns for different bind values. If the database marks the cursor bind-aware, then the next time that the cursor executes the database does the following:
· Generates a new plan based on the new bind value.
· Marks the original cursor generated for the statement
A bind-aware cursor is a bind-sensitive cursor eligible to use different plans for different bind values. After a cursor has been made bind-aware, the optimizer chooses plans for future executions based on the bind value and its selectivity estimate
Cursor merging
If the optimizer creates a plan for a bind-aware cursor, and if this plan is the same as an existing cursor, then the optimizer can perform. cursor merging. In this case, the database merges cursors to save space in the shared SQL area
做一組試驗測試一下該功能
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE 11.2.0.2.0 Production
TNS for IBM/AIX RISC System/6000: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 – Production
SQL> create table emp(id number(10), name varchar(500)) pctfree 40;
Table created.
SQL> begin
2 for i in 1..1000 loop
3 insert into emp values(1,lpad('x',300,'x'));
insert into emp values(i,lpad('y',300,'x'));
end loop;
commit;
end; 4 5 6 7
8 /
PL/SQL procedure successfully completed
SQL> create index t_ind on emp(id);
Index created.
案例1
開啟變數窺測,收集直方圖
SQL> exec dbms_stats.gather_table_stats('SYS','EMP',estimate_percent => 100, cascade => true, method_opt =>'for all columns size skewonly');
PL/SQL procedure successfully completed.
SQL> select column_name,NUM_BUCKETS,DENSITY,NUM_NULLS from dba_tab_columns where TABLE_NAME='EMP';
COLUMN_NAME NUM_BUCKETS DENSITY NUM_NULLS
-------------------------------------------------- ----------- ---------- ----------
NAME 1 .00025 0
ID 254 .0005 0
SQL> variable id number;
SQL> exec :id :=6;
PL/SQL procedure successfully completed.
SQL> select /*test*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 7jrqjukk5g62z, child number 0
-------------------------------------
select /*test*/ count(name) from emp where id = : id
Plan hash value: 1800857609
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 304 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_IND | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=:ID)
20 rows selected.
--檢視檢視,bind_sensitive=Y, bind_aware=N
SQL> SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS "BIND_SENSI",IS_BIND_AWARE AS "BIND_AWARE", IS_SHAREABLE AS "BIND_SHARE" FROM V$SQL where sql_id ='7jrqjukk5g62z';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BIND_SENSI BIND_AWARE BIND_SHARE
------------ ---------- ----------- ---------- ---------- ----------
0 1 25 Y N Y
SQL> select CHILD_NUMBER,BIND_SET_HASH_VALUE,PEEKED,EXECUTIONS,ROWS_PROCESSED,BUFFER_GETS,CPU_TIME from v$sql_cs_statistics where sql_id ='7jrqjukk5g62z';
CHILD_NUMBER BIND_SET_HASH_VALUE P EXECUTIONS ROWS_PROCESSED BUFFER_GETS CPU_TIME
------------ ------------------- - ---------- -------------- ----------- ----------
0 1021760792 Y 1 3 25 0
--更改繫結變數值
SQL> exec :id := 1;
PL/SQL procedure successfully completed.
SQL> select /*test*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1001
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 7jrqjukk5g62z, child number 0
-------------------------------------
select /*test*/ count(name) from emp where id = : id
Plan hash value: 1800857609
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 304 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_IND | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=:ID)
20 rows selected.
--第一次並不會更改執行計劃,但是v$sql.buffer_gets卻發生了改變,由25增加到162
SQL> SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS "BIND_SENSI",IS_BIND_AWARE AS "BIND_AWARE", IS_SHAREABLE AS "BIND_SHARE" FROM V$SQL where sql_id ='7jrqjukk5g62z';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BIND_SENSI BIND_AWARE BIND_SHARE
------------ ---------- ----------- ---------- ---------- ----------
0 2 162 Y N Y
SQL> select CHILD_NUMBER,BIND_SET_HASH_VALUE,PEEKED,EXECUTIONS,ROWS_PROCESSED,BUFFER_GETS,CPU_TIME from v$sql_cs_statistics where sql_id ='7jrqjukk5g62z';
CHILD_NUMBER BIND_SET_HASH_VALUE P EXECUTIONS ROWS_PROCESSED BUFFER_GETS CPU_TIME
------------ ------------------- - ---------- -------------- ----------- ----------
0 1021760792 Y 1 3 25 0
--第二次執行
SQL> select /*test*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1001
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 7jrqjukk5g62z, child number 1—生成了一個新的子游標
-------------------------------------
select /*test*/ count(name) from emp where id = : id
Plan hash value: 1849991560
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 39 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
|* 2 | TABLE ACCESS FULL| EMP | 984 | 292K| 39 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("ID"=:ID)
19 rows selected.
--新生成的子游標選擇全表掃描,且bind_aware=Y
SQL> SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS "BIND_SENSI",IS_BIND_AWARE AS "BIND_AWARE", IS_SHAREABLE AS "BIND_SHARE" FROM V$SQL where sql_id ='7jrqjukk5g62z';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BIND_SENSI BIND_AWARE BIND_SHARE
------------ ---------- ----------- ---------- ---------- ----------
0 2 162 Y N Y
1 1 140 Y Y Y
SQL> select CHILD_NUMBER,BIND_SET_HASH_VALUE,PEEKED,EXECUTIONS,ROWS_PROCESSED,BUFFER_GETS,CPU_TIME from v$sql_cs_statistics where sql_id ='7jrqjukk5g62z';
CHILD_NUMBER BIND_SET_HASH_VALUE P EXECUTIONS ROWS_PROCESSED BUFFER_GETS CPU_TIME
------------ ------------------- - ---------- -------------- ----------- ----------
1 2342552567 Y 1 1002 140 0
0 1021760792 Y 1 3 25 0
--此時將id改為一個可以使用索引掃描的值
SQL> exec :id :=100;
PL/SQL procedure successfully completed.
SQL> select /*test*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 7jrqjukk5g62z, child number 2
-------------------------------------
select /*test*/ count(name) from emp where id = : id
Plan hash value: 1800857609
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 304 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_IND | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=:ID)
20 rows selected.
--生成一個新的子游標,且第一個子游標被設定為不可共享
SQL> SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS "BIND_SENSI",IS_BIND_AWARE AS "BIND_AWARE", IS_SHAREABLE AS "BIND_SHARE" FROM V$SQL where sql_id ='7jrqjukk5g62z';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BIND_SENSI BIND_AWARE BIND_SHARE
------------ ---------- ----------- ---------- ---------- ----------
0 2 162 Y N N
1 1 140 Y Y Y
2 1 3 Y Y Y
SQL> select CHILD_NUMBER,BIND_SET_HASH_VALUE,PEEKED,EXECUTIONS,ROWS_PROCESSED,BUFFER_GETS,CPU_TIME from v$sql_cs_statistics where sql_id ='7jrqjukk5g62z';
CHILD_NUMBER BIND_SET_HASH_VALUE P EXECUTIONS ROWS_PROCESSED BUFFER_GETS CPU_TIME
------------ ------------------- - ---------- -------------- ----------- ----------
2 336594526 Y 1 3 3 0
1 2342552567 Y 1 1002 140 0
0 1021760792 Y 1 3 25 0
--第一個子游標已經被標識為不可共享,但若將id值重新改為6,還是可以重用
SQL> exec :id := 6;
PL/SQL procedure successfully completed.
SQL> select /*test*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 9jxcwk6y1fzpt, child number 0
-------------------------------------
select /*test*/ count(name) from emp where id = : id
Plan hash value: 1800857609
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 304 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_IND | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=:ID)
20 rows selected.
但是過了一會就無法再用了,有點奇怪
SQL> exec :id := 6;
PL/SQL procedure successfully completed.
SQL> select /*test*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 7jrqjukk5g62z, child number 2
-------------------------------------
select /*test*/ count(name) from emp where id = : id
Plan hash value: 1800857609
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 1 | 304 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_IND | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=:ID)
20 rows selected.
SQL> SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS "BIND_SENSI",IS_BIND_AWARE AS "BIND_AWARE", IS_SHAREABLE AS "BIND_SHARE" FROM V$SQL where sql_id ='7jrqjukk5g62z';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BIND_SENSI BIND_AWARE BIND_SHARE
------------ ---------- ----------- ---------- ---------- ----------
0 2 162 Y N N
1 1 140 Y Y Y
2 4 12 Y Y Y
--檢視子游標無法共享的原因
SQL> select CHILD_NUMBER,BIND_EQUIV_FAILURE,LOAD_OPTIMIZER_STATS from v$sql_shared_cursor where sql_id='7jrqjukk5g62z';
CHILD_NUMBER B L
------------ - -
0 N Y
1 Y N
2 Y N
-- BIND_EQUIV_FAILURE: The bind value's selectivity does not match that used to optimize the existing child cursor
-- LOAD_OPTIMIZER_STATS : A hard parse is forced in order to initialize extended cursor sharing
小結:當系統開啟繫結變數窺測且收集了直方圖時,oracle會對不同的繫結變數生成不同的子游標(但該變數必須執行至少兩次),並依據selectivity生成新的執行計劃
案例2
刪除直方圖
SQL> exec dbms_stats.delete_column_stats('SYS','EMP','ID',col_stat_type =>'HISTOGRAM');
PL/SQL procedure successfully completed.
SQL> select column_name,NUM_BUCKETS,DENSITY,NUM_NULLS from dba_tab_columns where TABLE_NAME='EMP';
COLUMN_NAME NUM_BUCKETS DENSITY NUM_NULLS
-------------------------------------------------- ----------- ---------- ----------
NAME 1 .00025 0
ID 1 .001 0
SQL> exec :id := 600;
PL/SQL procedure successfully completed.
SQL> select /*justin*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 6d84s04yqn3cp, child number 0
-------------------------------------
select /*justin*/ count(name) from emp where id = : id
Plan hash value: 1800857609
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 2 | 608 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_IND | 2 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=:ID)
20 rows selected.
SQL> SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS "BIND_SENSI",IS_BIND_AWARE AS "BIND_AWARE", IS_SHAREABLE AS "BIND_SHARE" FROM V$SQL where sql_id ='6d84s04yqn3cp';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BIND_SENSI BIND_AWARE BIND_SHARE
------------ ---------- ----------- ---------- ---------- ----------
0 1 22 Y N Y
SQL> select CHILD_NUMBER,BIND_SET_HASH_VALUE,PEEKED,EXECUTIONS,ROWS_PROCESSED,BUFFER_GETS,CPU_TIME from v$sql_cs_statistics where sql_id ='6d84s04yqn3cp';
CHILD_NUMBER BIND_SET_HASH_VALUE P EXECUTIONS ROWS_PROCESSED BUFFER_GETS CPU_TIME
------------ ------------------- - ---------- -------------- ----------- ----------
0 3287955162 Y 1 3 22 0
將id改為1
SQL> exec :id :=1;
PL/SQL procedure successfully completed.
SQL> select /*justin*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1001
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 6d84s04yqn3cp, child number 0
-------------------------------------
select /*justin*/ count(name) from emp where id = : id
Plan hash value: 1800857609
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 2 | 608 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_IND | 2 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=:ID)
20 rows selected.
SQL> select /*justin*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1001
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 6d84s04yqn3cp, child number 1
-------------------------------------
select /*justin*/ count(name) from emp where id = : id
Plan hash value: 1800857609
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 2 | 608 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_IND | 2 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=:ID)
20 rows selected.
--執行兩次後生成一個新的子游標,但是仍舊選擇索引掃描
SQL> SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS "BIND_SENSI",IS_BIND_AWARE AS "BIND_AWARE", IS_SHAREABLE AS "BIND_SHARE" FROM V$SQL where sql_id ='6d84s04yqn3cp';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BIND_SENSI BIND_AWARE BIND_SHARE
------------ ---------- ----------- ---------- ---------- ----------
0 2 159 Y N N
1 1 137 Y Y Y
SQL> select CHILD_NUMBER,BIND_SET_HASH_VALUE,PEEKED,EXECUTIONS,ROWS_PROCESSED,BUFFER_GETS,CPU_TIME from v$sql_cs_statistics where sql_id ='6d84s04yqn3cp';
CHILD_NUMBER BIND_SET_HASH_VALUE P EXECUTIONS ROWS_PROCESSED BUFFER_GETS CPU_TIME
------------ ------------------- - ---------- -------------- ----------- ----------
1 2342552567 Y 1 2003 137 0
0 3287955162 Y 1 3 22 0
小結:刪除直方圖,遊標依舊為bind_sensitive,但是即便生成了不同的子游標,由於缺乏足夠的統計資訊,當id=1時oracle依舊選擇了索引掃描
案例3
沒有直方圖,也不開啟繫結變數窺視
SQL> alter system set "_optim_peek_user_binds"=false;
System altered.
SQL> select /*thirid*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1001
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 01k335m3nbvty, child number 0
-------------------------------------
select /*thirid*/ count(name) from emp where id = : id
Plan hash value: 1800857609
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 2 | 608 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_IND | 2 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=:ID)
20 rows selected.
SQL> exec :id :=2;
PL/SQL procedure successfully completed.
SQL> select /*thirid*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 68jwfamnx5gty, child number 0
-------------------------------------
select /*thirid*/ count(name) from emp where id = : id
Plan hash value: 1800857609
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 2 | 608 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_IND | 2 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=:ID)
20 rows selected.
--可以看到只生成一個子遊標,且bind_sensitive=N
SQL> SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS "BIND_SENSI",IS_BIND_AWARE AS "BIND_AWARE", IS_SHAREABLE AS "BIND_SHARE" FROM V$SQL where sql_id ='01k335m3nbvty';
CHILD_NUMBER EXECUTIONS BUFFER_GETS BIND_SENSI BIND_AWARE BIND_SHARE
------------ ---------- ----------- ---------- ---------- ----------
0 1 137 N N Y
SQL> select CHILD_NUMBER,BIND_SET_HASH_VALUE,PEEKED,EXECUTIONS,ROWS_PROCESSED,BUFFER_GETS,CPU_TIME from v$sql_cs_statistics where sql_id ='01k335m3nbvty';
no rows selected
小結:沒有繫結變數窺測時,oracle不會生成不同的子游標
案例4
只有直方圖,沒有窺測
SQL> alter system set "_optim_peek_user_binds"=false;
System altered.
SQL> select /*fourth*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID ax6hs790n3ru2, child number 0
-------------------------------------
select /*fourth*/ count(name) from emp where id = : id
Plan hash value: 1800857609
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 2 | 608 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_IND | 2 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=:ID)
20 rows selected.
SQL> exec :id :=1;
PL/SQL procedure successfully completed.
SQL> select /*fourth*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1001
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 5ru3vdjyva40h, child number 0
-------------------------------------
select /*fourth*/ count(name) from emp where id = : id
Plan hash value: 1800857609
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 2 | 608 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_IND | 2 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=:ID)
20 rows selected.
SQL> select /*fourth*/ count(name) from emp where id = : id;
COUNT(NAME)
-----------
1001
SQL> select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 5ru3vdjyva40h, child number 0
-------------------------------------
select /*fourth*/ count(name) from emp where id = : id
Plan hash value: 1800857609
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 304 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 2 | 608 | 2 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | T_IND | 2 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=:ID)
20 rows selected.
SQL> SELECT CHILD_NUMBER, EXECUTIONS, BUFFER_GETS, IS_BIND_SENSITIVE AS "BIND_SENSI",IS_BIND_AWARE AS "BIND_AWARE", IS_SHAREABLE AS "BIND_SHARE" FROM V$SQL where sql_id ='5ru3vdjyva40h';
CHILD_NUMBER EXECUTIONS BUFFER_GETS B B B
------------ ---------- ----------- - - -
0 2 274 N N Y
SQL> select CHILD_NUMBER,BIND_SET_HASH_VALUE,PEEKED,EXECUTIONS,ROWS_PROCESSED,BUFFER_GETS,CPU_TIME from v$sql_cs_statistics where sql_id ='5ru3vdjyva40h';
no rows selected
小結:沒有繫結變數窺測時,oracle不會生成不同的子游標
總結:
11G若要正確的使用adaptive cursor sharing功能,必須開啟繫結變數窺視,且對應列需要收集直方圖資訊,兩者缺其一都會誤導oracle做出錯誤的選擇;
若只開啟peeking,則即便使用了adaptive cursor sharing生成不同的子游標,由於缺乏正確的統計資訊也可能導致沿用錯誤的執行計劃,若不開啟peeking則adaptive cursor sharing根本無從談起。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15480802/viewspace-736982/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 11G Adaptive Cursor Sharing(ACS)的研究APT
- Adaptive Cursor SharingAPT
- 11G Adaptive Cursor Sharing(ACS)的研究 (轉)APT
- Oracle 11g SQL效能的新特性(一)- Adaptive Cursor SharingOracleSQLAPT
- Adaptive Cursor Sharing(第二篇)APT
- Adaptive Cursor Sharing(第三篇)APT
- Adaptive Cursor Sharing(第四篇)APT
- Adaptive Cursor Sharing(第五篇)APT
- 11G Adaptive Cursor Sharing(ACS)自適應遊標測試APT
- Adaptive Cursor Sharing (第一篇)APT
- Adaptive Cursor Sharing: Worked Example (Doc ID 836256.1)APT
- 【DBA】Oracle 11g 針對SQL效能的新特性(一)- Adaptive Cursor SharingOracleSQLAPT
- 優化器革命之- adaptive cursor sharing (三)優化APT
- 優化器革命之- adaptive cursor sharing (二)優化APT
- 11GR1 新特性 adaptive cursor sharingAPT
- [20120327]Adaptive Cursor Sharing 的問題APT
- 最佳化器革命之- adaptive cursor sharing (三)APT
- 最佳化器革命之- adaptive cursor sharing (四)APT
- Cursor Sharing in Oracle Database 11gOracleDatabase
- Oracle自適應共享遊標——Adaptive Cursor Sharing(上)OracleAPT
- Oracle自適應共享遊標——Adaptive Cursor Sharing(下)OracleAPT
- 11gR2 新特性之(一)Adaptive Cursor Sharing(ACS)APT
- 揭秘自適應遊標共享技術(Adaptive Cursor Sharing)APT
- 繫結變數的正確使用,bind peeking,Adaptive Cursor Sharing變數APT
- 揭祕自適應遊標共享技術(Adaptive Cursor Sharing)APT
- Postgresql的CURSOR SHARINGSQL
- [20221227]Adaptive Cursor Sharing & 直方圖.txtAPT直方圖
- 繫結變數之自適應遊標共享(Adaptive Cursor Sharing)變數APT
- V$SQL_遊標、adaptive cursor sharing、bind peeking、直方圖的概念SQLAPT直方圖
- oracle11g中SQL最佳化新特性之Adaptive Cursor Sharing (ACS)OracleSQLAPT
- [20120220]Adaptive Cursor Sharing 與hints.txtAPT
- oracle實驗記錄 (cursor_sharing(2)SIMILAR)OracleMILA
- CURSOR_SHARING=SIMILARMILA
- oracle cursor_sharing [轉]Oracle
- Oracle 的 cursor_sharing引數Oracle
- oracle實驗記錄 (cursor_sharing(1)exact&force)Oracle
- 關於 cursor_sharing = similarMILA
- oracle引數-cursor_sharingOracle