♣
题目部分
在Oracle中,游标有哪几类?
♣
答案部分
游标(Cursor)是Oracle数据库中SQL解析和执行的载体,它可以分为共享游标(Shared Cursor)和会话游标(Session Cursor)。共享游标是指缓存在库缓存(Library Cache)里的一种库缓存对象,其实就是指缓存在库缓存里的SQL语句和匿名PL/SQL块所对应的库缓存对象。共享游标是Oracle缓存在库缓存中的几十种库缓存对象之一,它所对应的库缓存对象句柄的Namespace属性的值是CRSR(也就是Cursor的缩写)。共享游标会存储目标SQL的SQL文本、解析树、该SQL所涉及的对象定义、该SQL所使用的绑定变量类型和长度,以及该SQL的执行计划等信息。共享游标可以细分为父游标(Parent Cursor)和子游标(Child Cursor),可以通过视图V$SQLAREA来查看当前缓存在库缓存(Library Cache)中的父游标,而通过V$SQL来查看缓存在库缓存中的子游标。Oracle设计这种嵌套的Parent Cursor和Child Cursor并存的结构是为了能尽量减少对应的Hash Bucket中库缓存对象句柄链表的长度。
Oracle中游标的分类如下图所示:
图 3-13 Oracle中的游标分类
父游标和子游标的对比如下表所示:
父游标(Parent Cursor) | 子游标(Child Cursor) | |
---|---|---|
查询视图 | V$SQLAREA | V$SQL |
存储内容 | 父游标存储SQL文本(库缓存对象句柄的属性NAME中);父游标的 heap 0 中存储着子游标的句柄地址。 | 子游标存储解析树(Parse Tree)及执行计划(Execution Plan,实际上存储在库缓存对象句柄的heap 6中),以及该SQL所使用的绑定变量的类型和长度。 |
库缓存对象句柄的属性NAME存储内容 | 存储SQL文本 | 空 |
联系 | 1.父游标和子游标的结构是一样的,它们都是以库缓存对象句柄的方式缓存在库缓存中,Namespace属性的值均为CRSR。2.由于子游标所对应的库缓存对象句柄的NAME属性值为空,所以,只能通过父游标才能找到相应的子游标。3.任意一个经过解析的目标SQL一定会同时对应两个共享游标(Shared Cursor),一个是父游标(Parent Cursor),另一个则是子游标(Child Cursor)。 |
Oracle在解析目标SQL时去库缓存中查找匹配Shared Cursor的过程如下图所示:
从上图可以看出,Oracle在解析目标SQL时去库缓存中查找匹配共享游标(Shared Cursor)的过程包含如下几个步骤:
(1)根据目标SQL的SQL文本的哈希值去库缓存中查找匹配的Hash Bucket。
(2)然后在匹配的Hash Bucket的库缓存对象链表中查找匹配的父游标(Parent Cursor),当然,在查找匹配Parent Cursor的过程中肯定会比对目标SQL的SQL文本(因为不同的SQL文本计算出来的哈希值可能是相同的)。
(3)在步骤(2)中,如果找到了匹配的父游标,那么Oracle接下来就会遍历从属于该父游标的所有子游标以查找匹配的子游标。如果找不到匹配的父游标,那么也意味着此时没有可以共享的解析树和执行计划,Oracle就会从头开始解析上述目标SQL,新生成一个父游标和一个子游标,并把它们挂在对应的Hash Bucket中。在匹配的父游标中查找匹配的子游标时,如果找到了匹配的子游标,那么Oracle就会把存储于该子游标中的解析树和执行计划直接拿过来重用,而不用再从头开始解析。如果找不到匹配的子游标,那么意味着没有可以共享的解析树和执行计划,接下来Oracle也会从头开始解析上述目标SQL,新生成一个子游标,并把这个子游标挂在对应的父游标下。
本文选自《Oracle程序员面试笔试宝典》,作者:李华荣。