【DB笔试面试576】在Oracle中,简述Oracle中的游标。

【DB笔试面试576】在Oracle中,简述Oracle中的游标。

♣          题目         部分

在Oracle中,简述Oracle中的游标。


     
♣          答案部分          


 

在介绍游标之前先介绍一下Oracle数据库中库缓存(Library Cache)的作用及其组成结构。库缓存是SGA*享池(Shared Pool)中的一块内存区域,主要作用就是缓存执行过的SQL语句和PL/SQL语句(例如存储过程、函数、包、触发器)及其所对应的解析树(Parse Tree)和执行计划等信息。当同样的SQL语句和PL/SQL语句再次被执行的时候就可以直接利用已经缓存在库缓存中的那些相关对象而无须再次从头开始解析,这样就提高了这些SQL语句和PL/SQL语句在重复执行时的执行效率。库缓存(Library Cache)在SGA中的位置如下图所示:

 

【DB笔试面试576】在Oracle中,简述Oracle中的游标。

接下来需要明白如下几个概念:

l 库缓存对象(Library Cache Object,LCO):缓存在库缓存中的对象被称之为库缓存对象,包括SQL语句、PL/SQL语句、表、索引、包、触发器等。可以使用视图V$DB_OBJECT_CACHE(基表为X$KGLOB)来查询当前缓存在库缓存中的所有对象。

l 库缓存对象句柄(Library Cache Object Handle):所有的库缓存对象都是以一种名为库缓存对象句柄的结构存储在库缓存中,Oracle是通过访问相关的库缓存对象句柄来访问对应的库缓存对象的。所以,要访问库缓存对象,就需要先访问库缓存对象句柄。库缓存对象句柄是Oracle自定义的一种复杂的C语言结构。由于库缓存对象句柄是以哈希表(Hash Table)的方式存储在库缓存中的,哈希表就是很多Hash Bucket组成的数组,所以,Oracle会通过相关的哈希运算来存储和访问对应的库缓存对象句柄。

整个库缓存的组成结构如下图所示:

 

【DB笔试面试576】在Oracle中,简述Oracle中的游标。

从上图可以看出,整个库缓存可以看作是由一组Hash Bucket所组成,每一个Hash Bucket都对应不同的哈希值(Hash Value)。对于单个Hash Bucket而言,里面存储的就是哈希值相同的所有库缓存对象句柄,同一个Hash Bucket中不同的库缓存对象句柄之间会用指针连接起来,即同一个Hash Bucket中不同的库缓存对象句柄之间实际上组成了一个库缓存对象句柄链表(Library Cache Object Handles)。

当Oracle要执行目标SQL“select * from lhr.emp”时,首先会对该SQL的SQL文本进行哈希运算,然后根据得到的哈希值找到相关的Hash Bucket,在Hash Bucket中遍历对应的库缓存对象句柄链表。如果找到了对应的库缓存对象句柄,那么就可以直接访问到该SQL的执行计划、解析树等对象,这意味着可以直接重用这些对象而无须再次从头开始解析:如果找不到对应的库缓存对象句柄,那么意味着必须从头开始解析,并且把解析后的执行计划、解析树等对象以库缓存对象句柄的方式链接在相关的Hash Bucket中的库缓存对象句柄链表中。

由于库缓存对象句柄是Oracle自定义的一种复杂的C语言结构,所以,库缓存对象句柄有很多属性,每一个属性都有其特定的作用,这里介绍Name、Namespace和Heap 0 Pointer这3个属性。

l 属性“Name”表示的是库缓存对象句柄所对应的库缓存对象的名称。例如,如果库缓存对象是SQL语句,那么属性“Name”的值就是该SQL的SQL文本:如果库缓存对象是表,那么属性“Name”的值就是该表的表名。

l 属性“Namespace”表示的是库缓存对象句柄对应的库缓存对象所在的分组名,不同类型的库缓存对象可能属于同一个分组,即不同类型的库缓存对象所对应的库缓存对象句柄的Namespace值有可能是相同的。例如,SQL语句和匿名PL/SQL块所对应的库缓存对象句柄的Namespace的值就都是CRSR。Oracle数据库中常见的Namespace的值和其对应的含义如下表所示:

Namespace值

含义

CRSR

SQL语句和匿名PL/SQL块所对应的库缓存对象句柄的Namespace的值均为“CRSR”

TABL/PRCD/TYPE

表、视图、序列、同义词、存储过程、函数、Type和Package的定义所对应的库缓存对象句柄的Namespace的值均为“TABL/PRCD/TYPE”

BODY/TYBD

Type和Package的具体实现(Body)所对应的库缓存对象句柄的Namespace的值均为“BODY/TYBD”

TRGR

触发器所对应的库缓存对象句柄的Namespace的值为“TRGR”

INDX

索引所对应的厍缓存对象句柄的Namespace的值为“INDX”

CLST

Cluster所对应的库缓存对象句柄的Namespace的值为“CLST”

l 属性“Heap 0 Pointer”是指向子结构Heap 0的指针,是一种嵌套结构。Heap 0的结构较为复杂,它有很多属性,每一个属性都有其特定的作用,这里介绍Tables和Data Blocks Pointer这两个属性。

① 属性“Tables”里记录的是与该Heap 0所在的库缓存对象有关联关系的库缓存对象句柄地址的集合。“Tables”又细分为很多类(从Dependency table到Schema name table),其中最值得关注的就是“Child table”。“Child table”里记录的就是从属于该Heap 0所在的库缓存对象的子库缓存对象的句柄地址的集合。Heap 0里的“Tables”实际上记录的就是各个库缓存对象之间的关联关系,Oracle可以通过这些关联关系直接访问到对应的库缓存对象。例如,Oracle可以通过访问某个库缓存对象的Heap 0中的Child table而依次顺序访问从属于该对象的所有子库缓存对象。

② 对每一个库缓存对象而言,都或多或少需要往库缓存中存储一些该库缓存对象所特有的动态运行时(runtime)数据,比如SQL语句所对应的库缓存对象就需要在库缓存中缓存该SQL语句所对应的编译好的二进制格式的执行计划。Oracle会用Data Heap来存储这些动态运行时数据,所谓的“Data Heap”,可以简单地理解成是库缓存中的一块连续的内存区域,Data Heap是动态分配的,其大小并不固定。每一个库缓存对象都可能会拥有多个Data Heap,这里分别将它们命名为Heap 1、Heap 2、……、Heap n。各个Data Heap之间是独立的,没有关联关系,Oracle会在Heap 0的属性“Data Blocks Pointer”中存储指向这些Data Heap的指针,这样Oracle通过访问Heap 0就可以按需访问该Heap 0所在的库缓存对象拥有的所有Data Heap了。


上一篇:图解堆排序算法


下一篇:JVM系列之:再谈java中的safepoint