当用户提交SQL语句或PL/SQL程序块到oracle的shared pool以后,在library cache中生成的一个可执行的对象,这个对象就叫做游标(cursor)。不要把这里的游标与标准SQL(ANSI SQL)的游标混淆起来了,标准SQL的游标是指返回多条记录的SQL形式,需要定义、打开、关闭。下面所说到的游标如无特别说明,都是指library cache中的可执行的对象。游标是可以被所有进程共享的,也就是说如果100个进程都执行相同的SQL语句,那么这100个进程都可以同时使用该SQL 语句所产生的游标,从而节省了内存。每个游标都是由library cache中的两个或多个对象所体现的,至少两个对象。一个对象叫做父游标(parent cursor),包含游标的名称以及其他独立于提交用户的信息。v$sqlarea视图里看到的都是有关父游标的信息;另外一个或多个对象叫做子游标(child cursors),如果SQL文本相同,但是可能提交SQL语句的用户不同,或者用户提交的SQL语句所涉及到的对象为同名词等,都有可能生成不同的子游标。因为这些SQL语句的文本虽然完全一样,但是上下文环境却不一样,因此这样的SQL语句不是一个可执行的对象,必须细化为多个子游标后才能够执行。子游标含有执行计划或者PL/SQL对象的程序代码块

 

 

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语句只有在它们的文本完全一致的情况下才能共享一个父游标,这是最基本的要求。

 

如果产生了子游标,那么说明肯定产生了某种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 tt');

KGLHDPAR ADDRESS  A T O
-------- -------- - - -
89BB8948 89BB83CC N N N
89BB8948 89BB5E78 N N Y
可以看到OPTIMIZER_MISMATCH列第二行的值为Y,这说明了正是由于optimizer_mode的不同而产生了子游标。
最后,父游标和子游标的意义何在?其实一切都是为了共享。以减少再次解析的资源浪费。

 

 

 

查询v$db_object_cache来显示library cache中有哪些对象被缓存,以及这些对象的大小尺寸。

我们可以用下面的SQL语句来显示每个namespace中,大小尺寸排在前3名的对象:

SELECT   *
    FROM (SELECT   ROW_NUMBER () OVER (PARTITION BY namespace ORDER BY sharable_mem DESC)
                                                                    size_rank,
                   namespace, sharable_mem, SUBSTR (NAME, 1, 50) NAME
              FROM v$db_object_cache
          ORDER BY sharable_mem DESC)
   WHERE size_rank <= 3
ORDER BY namespace, size_rank;

 

posted on 2010-11-17 17:45  Alex.Zhang  阅读(727)  评论(0编辑  收藏  举报