recursive calls并不仅仅发生在解析的时候。由于数据字典记录了所有对象的结构、数据信息,因此在对象结构(如dba_tables、dba_objects)、数据发生变化(如统计信息的视图、段视图dba_segments(即占用空间会变化))时都会访问数据字典
数据字典是有关于数据库的参考信息、数据库的结构信息和数据库中的用户信息的一组表和视图的集合,如我们常用到的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的用户都可以访问这两个地方以获取数据字典信息。