v$sql v$sqlarea v$sql_shared_cursor及游标
1.v$sql和v$sqlarea的区别
v$sql和v$sqlarea从某种意义上具有父子关系。即v$sqlarea保存的是父游标的sql信息,而v$sql保存的是子游标的sql的信息。在v$sqlarea里面有一列VERSION_COUNT字段,其中代表的就是对于此父游标的子游标的数量,也就是在v$sql里面的子游标的sql记录的数量。在v$sql中有一列CHILD_NUMBER字段,表示该字游标的编号。可以说v$sqlarea和v$sql是一对多的父子关系。
2.父游标和子游标
每种类型的dml语句都需要如下阶段:
Create a Cursor 创建游标
Parse the Statement 分析语句
Bind Any Variables 绑定变量
Run the Statement 运行语句
Close the Cursor 关闭游标
当数据库第一次对一条SQL语句进行硬解析的时候,会在库缓存中分配一些内存,并将新产生的父游标保存进去。与父游标有关的关键信息室这个SQL语句的文本,这个时候,会在v$sqlarea里面插入一条记录。那么,在什么情况下会产生子游标呢,当数据库又碰到一条完全相同SQL语句,但是语句的执行计划和执行环境发生了变化,比如由于绑定变量窥测而产生的不一致的执行计划,由于SQL的初始化参数optimizer_mode的不同以及绑定变量分级的情况都会产生子游标,当产生子游标的时候,会在v$sql里面插入一条记录。并且v$sqlarea里的VERSION_COUNT字段的值会加1。
eg:
--多个SQL语句只有在它们的文本完全一致的情况下才能共享一个父游标,这是最基本的要求。
--窗口1执行
sys/SYS>select * from t;
no rows selected
sys/SYS>select * from t;
no rows selected
sys/SYS>SELECT * from t;
no rows selected
--窗口2执行
sys/SYS>select hash_value,sql_text,executions from v$sqlarea where sql_text like '%from t';
HASH_VALUE SQL_TEXT EXECUTIONS
---------- ---------------------------------------- ----------
3542409071 SELECT * from t 1
520543201 select * from t 2
可以看到由于SQL文本不同产生了两个父游标。
sys/SYS>select HASH_VALUE,child_number,sql_text from v$sql where sql_text like '%from t';
HASH_VALUE CHILD_NUMBER SQL_TEXT
---------- ------------ ----------------------------------------
520543201 0 select * from t
3542409071 0 SELECT * from t
在v$sql里面也插入了两条子游标的记录,但是CHILD_NUMBER都是0,其实对应的就是父游标。
现在再来看下由于optimizer_mode的不同而产生子游标的情况。
--窗口1执行
sys/SYS>alter session set optimizer_mode=all_rows;
Session altered.
sys/SYS>select * from zyh;
no rows selected
sys/SYS>alter session set optimizer_mode=first_rows_10;
Session altered.
sys/SYS>select * from zyh;
no rows selected
--窗口2执行
sys/SYS>select hash_value,sql_text,executions,VERSION_COUNT from v$sqlarea where sql_text like '%from zyh';
HASH_VALUE SQL_TEXT EXECUTIONS VERSION_COUNT
---------- ---------------------------------------- ---------- -------------
3762890390 select * from zyh 2 2
sys/SYS>select HASH_VALUE,child_number,sql_text from v$sql where sql_text like '%from zyh';
HASH_VALUE CHILD_NUMBER SQL_TEXT
---------- ------------ ----------------------------------------
3762890390 0 select * from zyh
3762890390 1 select * from zyh
可以看到,SQL文本是完全相同的,所以两个子游标共享了一个父游标。但是由于optimizer_mode的不同,所以生成了2个子游标。
如果产生了子游标,那么说明肯定产生了某种mismatch,那么如何来查看是何种原因产生了mismatch呢?这就要通过v$sql_shared_cursor了。
sys/SYS>select kglhdpar, address,auth_check_mismatch, translation_mismatch,OPTIMIZER_MISMATCH
2 from v$sql_shared_cursor
3 where kglhdpar in
4 ( select address
5 from v$sql
6 where sql_text like '%from zyh');
KGLHDPAR ADDRESS A T O
-------- -------- - - -
89BB8948 89BB83CC N N N
89BB8948 89BB5E78 N N Y
可以看到OPTIMIZER_MISMATCH列第二行的值为Y,这说明了正是由于optimizer_mode的不同而产生了子游标。
最后,父游标和子游标的意义何在?其实一切都是为了共享。以减少再次解析的资源浪费。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/23891491/viewspace-744755/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/23891491/viewspace-744755/