shared SQL,parent cursor,child cursor
近日有朋友問到 cursor 如何確定是否sharable的,Metalink Note 296377.1 說得比較好,簡單註釋如下:
1. shared SQL,parent cursor,child cursor 概念:
所有SQL都是Oracle暗式共享的(implicitly sharable)。當使用者A發出一條SQL後,Oracle會根據SQL文字內容生成hash value(10g還有唯一的SQL_ID),以便能夠快速找到 Shared pool已經存在的相同SQL。如果找不到,則Oracle會為這個SQL建立一個parent cursor和一個child cursor,這與SQL是否共享是沒有關係的。
parent cursor包含了SQL TEXT和相關的hash value,v$sqlarea中的每一行代表了一個parent cursor,根據address表示了其記憶體地址。
child cursor包含了SQL的metadata,即使得這個SQL可以執行的所有相關資訊,如OBJECT和許可權,優化器設定,執行計劃等。v$sql中中的每一行表示了一個child cursor,根據hash value和address與parent cursor 關聯。child cursor有自己的address,即V$SQL.CHILD_ADDRESS。
第一個child cursor總是使用0來表示其建立順序,V$SQL.CHILD_NUMBER = 0。因此,當從V$SQL_PLAN中查詢某個SQL的執行計劃時,要注意你寫對了CHILD_NUMBER 。
如果有多個child cursor,則表示parent cursor有多個版本,v$sqlarea中的version_count欄位就會紀錄下來。
2. 如何確定SQL 是否可以共享:
假設使用者A執行完一條SQL後,退出然後重新登陸,發出同一條SQL,則根據hash value找到Shared pool中已經存在的parent cursor,然後把 此parent cursor下的child cursor list搜尋一邊,判斷metadata是否完全相同,如果是,則這條sql可以共享,就完成了一次soft parse。
假設使用者B之後發出一條SQL文字完全一樣的SQL,但訪問的table不是A使用者的,而是B使用者自己的,則metadata出現AUTH_CHECK_MISMATCH 和
TRANSLATION_MISMATCH ,無法共享child cursor。Oracle會因此在此parent cursor 下建立一個新的child cursor,也就是一個hard parse。
因此,SQL 是否可以共享是與parent cursor無關的,而是由child cursor決定的。
從v$sql_shared_cursor可以獲得詳細的無法共享的原因:
select * from v$sql_shared_cursor where kglhdpar =
select * from v$sql_shared_cursor where address =
一般常見的mismatch是:
OPTIMIZER_MISMATCH : 優化器環境設定不同,一般是optimizer相關引數
BIND_MISMATCH : 繫結變數的值的長度在第二次執行的時候發生顯著的變化 AUTH_CHECK_MISMATCH : 授權關係不匹配
TRANSLATION_MISMATCH: 事務環境不匹配
其實最常見的是 BIND_MISMATCH ,在10g中可以測試一下:
create table t1(col1 varchar2(4000));
declare
v_col1 varchar2(4000);
begin
v_col1 := 't';
for i in 1..30 loop
v_col1 := v_col1 ||'t';
insert into t1 values(v_col1);
end loop;
end;
/
--可以看出,變數長度在30以下的時候,還是隻有一個child cursor:
SQL_TEXT EXECUTIONS CHILD_NUMBER ADDRESS HASH_VALUE
--------------------------- ---------- ------------ -------- ----------
INSERT INTO T1 VALUES(:B1 ) 30 0 9E355F10 2351142747
declare
v_col1 varchar2(4000);
begin
v_col1 := 'tttttttttttttttttttttttttttttt';
for i in 31..4000 loop
v_col1 := v_col1 ||'t';
insert into t1 values(v_col1);
end loop;
end;
/
--可以看出,變數長度變化導致了四個child cursor 存在:
SQL_TEXT EXECUTIONS CHILD_NUMBER CHILD_ADDRESS ADDRESS HASH_VALUE
---------------------------- ---------- ------------ ------------- -------- ----------
INSERT INTO T1 VALUES(:B1 ) 32 0 9E355DCC 9E355F10 2351142747
INSERT INTO T1 VALUES(:B1 ) 96 1 9E34BA18 9E355F10 2351142747
INSERT INTO T1 VALUES(:B1 ) 1872 2 9E34B8D4 9E355F10 2351142747
INSERT INTO T1 VALUES(:B1 ) 2060 3 9E34B790 9E355F10 2351142747
3. 使用cursor trace獲得child cursor 無法共享的詳細原因:
--9i
alter session set events '10270 trace name context forever, level 10';
--10g
alter system set events 'immediate trace name cursortrace level 577, address
--(level 578/580 can be used for high level tracing (577=level 1, 578=level 2, 580=level 3)
alter system set events 'immediate trace name cursortrace level 2147483648, address 1';
4. cursor_sharing=similar 和 force 時的行為
cursor_sharing=similar 時
如果 predicate 為範圍( >,=,<= ),則出現literal replacement 時,一般不會share cursor,除非literal 完全相等;
因為在CBO下,這個時候的literal被用來確定執行計劃,literal replacement會被認 為是UNSAFE的,無法共享。
在RBO時候,CURSOR是會共享的。
CBO下,如果 predicate 為=,則出現literal replacement 時,是否share cursor,取決於這個column是否有histgrams。
cursor_sharing=force 時,不管 predicate,如果出現literal replacement ,則會shared cursor,但往往容易得到效能較差的執行計劃。
可以使用10046 判斷一個bind variable 是否 unsafe:
The flag oacfl2 in 9i and fl2 in 10g will show if a variable is unsafe.
BINDS #2:
bind 0: dty=2 mxl=22(04) mal=00 scl=00 pre=00 acflg=10 oacfl2=500 size=24 ffset=0 bfp=1036d6408 bln=22 avl=04 flg=09 value=16064
bind 1: dty=2 mxl=22(04) mal=00 scl=00 pre=00 acflg=10 oacfl2=500 size=24 ffset=0 bfp=1036d4340 bln=22 avl=04 flg=09
If you note oacfl2=500
#define UACFBLTR 0x00000100 /* Bind was generated by LiTeRal replacement */
#define UACFUNSL 0x00000200 /* UNSafe Literal */
#define UACFNDTL 0x00000400 /* Non-DaTa LiteRal */
在11g中,child cursor 共享這部分改動不小,如果從10g升級上去,AWR往往發現某些SQL的VERSION COUNT會變多,可能會命中BUG。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22990797/viewspace-713050/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- v$sqlarea_parent cursor_v$sql_child cursor關係SQL
- sql_shared_cursor (轉)SQL
- cursor_sharing與v$sqlarea_v$sql_v$sql_shared_cursorSQL
- 【CURSOR】Oracle 子游標無法共享的原因之V$SQL_SHARED_CURSOROracleSQL
- v$sql_shared_cursor中的BIND_MISMATCHSQL
- v$sql v$sqlarea v$sql_shared_cursor及遊標SQL
- PL/SQL cursorSQL
- V$SQL_SHARED_CURSOR檢視硬解析的原因SQL
- 11G can flush one SQL Cursor out of shared poolSQL
- SQL 遊標cursorSQL
- SQL Plan Baseline與Shared Cursor機制研究(一)SQL
- SQL Plan Baseline與Shared Cursor機制研究(二)SQL
- SQL Plan Baseline與Shared Cursor機制研究(三)SQL
- sql執行計劃_v$sqlarea_v$sql_v$sql_shared_cursorSQL
- v$sql_shared_cursor檢視記錄多版本的資訊SQL
- v$sql v$sqlarea v$sql_shared_cursor及父遊標,子游標SQL
- display_cursor_9i.sqlSQL
- PL/SQL 04 遊標 cursorSQL
- Oracle Shared Cursor問題的幾個實驗Oracle
- SQL 遊標cursor的運用SQL
- 檢視v$sql_shared_cursor檢視獲取sql語句為什麼不能共享?SQL
- 【CURSOR】Oracle 遊標 (cursor)知識梳理Oracle
- jQuery parent>child選擇器jQuery
- 【實驗】shared_pool的sql命中率--cursor_sharing引數研究SQL
- Oracle CursorOracle
- open_cursor & session_cached_cursor實驗Session
- 理解V$OPEN_CURSOR,SESSION_CACHED_CURSORSession
- 從共享遊標shared cursor角度看forall批量繫結
- 理解V$OPEN_CURSOR, V$SESSION_CACHED_CURSORSession
- [zt] 理解V$OPEN_CURSOR, V$SESSION_CACHED_CURSORSession
- SQL多版本控制 - _CURSOR_OBSOLETE_THRESHOLDSQL
- Oracle:cursor:mutex XOracleMutex
- ActiveMQ - message cursorMQ
- 'cursor:mutex ..'/ 'cursor:pin ..'/ 'library cache:mutex ..'型別的等待事件Mutex型別事件
- Precompiler HOLD_CURSOR and RELEASE_CURSOR Options (Doc ID 2055810.6)Compile
- 11gr2,V$OPEN_CURSOR增加cursor_type欄位
- firefox css cursor handFirefoxCSS
- cursor: mutex S等待事件Mutex事件