天天看点

什么时候会发生回调(recursive calls)

recursive calls并不仅仅发生在解析的时候。由于数据字典记录了所有对象的结构、数据信息,因此在对象结构(如dba_tables、dba_objects)、数据发生变化(如统计信息的视图、段视图dba_segments(即占用空间会变化))时都会访问数据字典

1.1.4.2.            字典缓存(Dictionary Cache)

数据字典是有关于数据库的参考信息、数据库的结构信息和数据库中的用户信息的一组表和视图的集合,如我们常用到的V$视图、DBA_视图都属于数据字典。在SQL语句解析的过程中,Oracle可以非常迅速的访问(如果需要的话)这些数据字典,在SQL Trace中,这种对数据字典的访问就被统计为回调(recursive calls)。看下面例子:

第一调用语句,需要做硬解析:

SQL> select * from T_COMPANY;           
9999 rows selected.           
Execution Plan           
----------------------------------------------------------           
Plan hash value: 3356521258           
-------------------------------------------------------------------------------           
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |           
-------------------------------------------------------------------------------           
|   0 | SELECT STATEMENT  |           | 10000 |   156K|     9   (0)| 00:00:01 |           
|   1 |  TABLE ACCESS FULL| T_COMPANY | 10000 |   156K|     9   (0)| 00:00:01 |           
-------------------------------------------------------------------------------           
Statistics           
----------------------------------------------------------           
        355  recursive calls           
          0  db block gets           
        764  consistent gets           
         39  physical reads           
        116  redo size           
     305479  bytes sent via SQL*Net to client           
       7711  bytes received via SQL*Net from client           
        668  SQL*Net roundtrips to/from client           
          5  sorts (memory)           
          0  sorts (disk)           
       9999  rows processed           

可以看到,Recursive Calls高达355。第二次调用,无需解析,直接使用共享SQL区中缓存:

SQL> /           
9999 rows selected.           
Execution Plan           
----------------------------------------------------------           
Plan hash value: 3356521258           
-------------------------------------------------------------------------------           
| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |           
-------------------------------------------------------------------------------           
|   0 | SELECT STATEMENT  |           | 10000 |   156K|     9   (0)| 00:00:01 |           
|   1 |  TABLE ACCESS FULL| T_COMPANY | 10000 |   156K|     9   (0)| 00:00:01 |           
-------------------------------------------------------------------------------           
Statistics           
----------------------------------------------------------           
          0  recursive calls           
          0  db block gets           
        705  consistent gets           
          0  physical reads           
          0  redo size           
     305479  bytes sent via SQL*Net to client           
       7711  bytes received via SQL*Net from client           
        668  SQL*Net roundtrips to/from client           
          0  sorts (memory)           
          0  sorts (disk)           
       9999  rows processed           

由于没做解析,这时recursive calls为0。

当然,recursive calls并不仅仅发生在解析的时候。由于数据字典记录了所有对象的结构、数据信息,因此在对象结构(如dba_tables、dba_objects)、数据发生变化(如统计信息的视图、段视图dba_segments(即占用空间会变化))时都会访问数据字典:

SQL> delete from t_company where rownum=1;           
1 row deleted.           
...           
Statistics           
----------------------------------------------------------           
        360  recursive calls           
...           
SQL> /           
1 row deleted.           
...           
Statistics           
----------------------------------------------------------           
          4  recursive calls           
...           
SQL> /           
...           
Statistics           
----------------------------------------------------------           
          4  recursive calls           
...           

可以看到,上面的delete语句在第一次执行时,包括因(SQL语句)解析和数据改动导致对数据字典的访问,因此

recursive calls较高,为360。在随后的执行中,因为没有做(SQL语句)解析,所以recursive calls大大减少,只有

4,而这4个recursive calls是因为数据改变而需要对数据字典的访问。

因为Oracle对数据字典访问如此频繁,因此内存中有两处地方被专门用于存放数据字典:

一个地方就是数据字典缓存(Data Dictionary Cache)。数据字典缓存也被称为行缓存(Row Cache),因为它是以记录行为单元存储数据的,而不像Buffer Cache是以数据块为单元存储数据。

内存中另外一个存储数据字典的地方是库缓存。

所有Oracle的用户都可以访问这两个地方以获取数据字典信息。

继续阅读