SQL解析过程分了3个大的阶段:
1、 语法检查
a) 对SQL语句进行语法检查,看是否有语法错误。比如没有写from等。
2、 语意检查
a) 到数据字典里校验SQL语句涉及的对象和列是否都存在。
b) 将对象进行名称转换。比如将同义词翻译成实际的对象等。
c) 检查游标里用户是否具有访问SQL语句里所引用的对象的权限。
3、 解析阶段
a) ORACLE首先将SQL文本转化为ASCII字符,然后根据HASH函数计算其对应的HASH(hash_value),再根据计算的HASH值到library cache中找到对应的bucket,然后比较bucket里是否存在该SQL语句。如果找不到的话就会获取shared pool latch,然后在shared pool中的可用chunk链表(也就是bucket)上找到一个可用的chunk,最后释放shared pool latch。
这个处理方式其实和JAVA中的HASHMAP非常相似,下次再介绍一下JAVA的HASHMAP。
首先通过HASH值找到HASH BUCKET,然后在其对应的链表中找(这个链表中有很多Library Cache Handle,因为很可能计算出的HASH值是一样的,为了解决HASH值冲突,所以在其上又引用了链表[在C#中解决方法是:如果HASH值一样就会重新计算HASH值,这样存储效率就打折扣了],如果计算的HASH值一样,就会将其存储在其链表上)Library cache handle;注意:匹配library cache handle时必须完全匹配,包括字符大小写,空格,注释等。
可以通过v$sql查看执行的SQL语句。
a) 如果文本完全匹配,则需要检查对象相关性,因为有可能SQL对象与library cache的同名对象属于不同的OWNER。
b) 即使对象匹配,绑定文本也一样了,也不能确保做软解析。有下面几个因素会造成不能软解析:
i. 绑定名不一样
SELECT * FROM employees WHERE department_id = :department_id;
SELECT * FROM employees WHERE department_id = :dept_id;
ii. 绑定数据类型和绑定变量长度不一样
BIND_MISMATCH(绑定不匹配)
Varchar2(100)与varchar2(400)不一样
字符串绑定变量
上面的测试,动态的授予变量类型长度
A varchar2(‘||i||’) –> i从1到4000
ORACLE 9I后提供了一个视图v$sql_shared_cursor来查看不能绑定的原因。
注意:硬解析结束以后,会为该SQL产生两个游标,一个是父游标,另一个是子游标,每个游标都是由library cache中的两个或多个对象所体现的,至少两个对象。一个对象叫做父游标(parent cursor),包含游标的名称以及其他独立于提交用户的信息。从v$sqlarea视图里看到的都是有关父游标的信息;另外一个或多个对象叫做子游标(child cursors),如果SQL文本相同,但是可能提交SQL语句的用户不同,或者用户提交的SQL语句所涉及到的对象为同义词等,都有可能生成不同的子游标。因为这些SQL语句的文本虽然完全一样,但是上下文环境却不一样,因此这样的SQL语句不是一个可执行的对象,必须细化为多个子游标后才能够执行。
子游标含有执行计划或者PL/SQL对象的程序代码块等。
V$SQL里面就是子游标的信息。
Library cache对象有两种:
临时对象
存储对象
最典型的临时对象是CURSOR,包括SELECT,DML,DCL,DDL
最典型的存储对象是预编译对象存储过程,函数,触发器,包等。
这里最重要的就是游标对象:
游标分临时游标和永久对象里的游标。
一个游标对象有两部分组成(父游标和子游标),而父游标和子游标对象,各分别有两部分组成,句柄library cache handle(heap 0)和library cache object(heap 非0)。那么父游标通常只有heap 0,而子游标有句柄(heap 0)和library cahce object(heap 非0),其中最关注的是library cache object(heap 非0)。
我们要执行一个SQL,首先要匹配这个父游标的文本,所以,首先要进行HASH运算,如果没有匹配,则需要shared pool latch来申请生成,并需要获取library cache load latch,把它装载进去。如果有匹配的父游标,为了防止在解析阶段,解析相关联的对象被DDL等,所以需要LOCK住句柄。
Library cache中的CURSOR信息是公有的(属于SHARED POOL),而当解析完后(硬解析,软解析或软软解析)要将共享CURSOR实例化到私有CURSOR才能执行。
父游标里主要包含两种信息:SQL文本以及优化目标(optimizer goal)
子游标包括游标所有的信息,比如具体的执行计划,绑定变量等。
7、即使对象匹配,绑定文本也一样了,也不能确保做软解析
8、语言、优化、排序环境不一样
9、通过优化器创建一个最优的执行计划(这一步最消耗CPU资源)
10、将该游标所产生的执行计划、SQL文本等装载进library cache中
在硬解析的过程中,进程会一直持有library cache latch,直到硬解析结束。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25285600/viewspace-772721/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/25285600/viewspace-772721/