oracle硬解析、软解析、软软解析(open_cursors)散记

汇总:

硬解析Hard parses
解决方法:
1.绑定变量
2.看shared pool是否太小或者变小(子游标放在Sga-shared pool-library cache)awr 搜shared pool可以看到大小改变:
这时候如果出现大量的硬解析,就会出现这个等待。最终的原因是因为一个全表扫描导致oracle的SGA自动管理把share pool缩小来增大DB CACHE,踢出去了一部分的执行计划,最终导致硬解析增加,最后设置一个share pool的最小值,并增大SGA的大小解决。

软解析
解决方法:
open_cursors加大 决定每个会话可以同时打开的游标数
SESSION_CACHED_CURSORS加大 此参数为软软解析 决定每个会话可以缓存的游标数
11203及以上_cursor_obsolete_threshold
11107/11201/11202改_cursor_features_enabled+106001

软软解析
小无敌

个人理解

硬解析:
首次执行的语句
解决方法:
绑定变量

软解析:
相同语句的sql缓存到shared pool的library cache中,下次执行直接从library cache中调用,
父游标相同(语句相同),子游标相同(环境相同),必须子游标相同为软解析
解决方法:
设置_cursor_obsolete_threshold(11.2.0.3及以上)或_cursor_features_enabled(11.2.0.2.2)值(mos296377.1)。

SQL> alter system set “_cursor_features_enabled”=34 scope=spfile;
System altered.
SQL> alter system set event=‘106001 trace name context forever,level 1024’ scope=spfile;
System altered
在这里插入图片描述

当游标数超过值后就不能缓存新的游标了,也就是无法产生软解析


DBA的思想天空作者的软解析和软软解析的理解

只要父游标相同即可为软解析(也就是只要语句相同,不用管环境),不同环境产生新的子游标(子游标数量由version决定),产生新的子游标也算软解析。
父游标+子游标都相同为软软解析,即软软解析为软解析的一种情况

软软解析:
等于不解析,完全跳过硬解析所有步骤。
当设置了session_cached_cursors参数,当某个session第三次执行相同的SQL语句后(相同环境下,第一次为硬解析,第二次且(游标数+游标缓存数)没到上限为软解析,第三次为软软解析,从pga中找执行计划),会把语句的游标信息转移到该session的PGA中。这样,当该session在执行该SQL语句时,会直接从PGA中取出执行计划,从而跳过硬解析的所有步骤。


open_cursors与session_cached_cursor的作用

在这里插入图片描述

open_cursors设定每个session(会话)最多能同时打开多少个cursor(游标)。session_cached_cursor设定每个session(会话)最多可以缓存多少个关闭掉的cursor。

SESSION_CACHED_CURSORS的值就是说的是一个session可以缓存多少个cursor,让后续相同的SQL语句不再打开游标,从而避免软解析的过程来提高性能。(绑定变量是解决硬解析的问题),软解析同硬解析一样,比较消耗资源.所以这个参数非常重要。


SQL解析的相关说明,理解,归纳

1、Oracle 对 SQL 的处理过程      
    1)语法检查(Syntax Check),检查此 SQL 的拼写是否符合语法
    2)语义检查(Semantic Check), 检查诸如 SQL 语句中的访问对象是否存在及该用户是否具备相应的权限
    3)对 SQL 语句进行解析(Prase),利用内部算法对 SQL 进行解析,生成解析树(Parse Tree)及执行计划(Execution Plan)
    4)执行SQL,并返回结果(Execute and Return)

2、Oracle 在解析 目标SQL 时在 Library Cache 中匹配的过程
    1)首先基于对应 LCO Handle(库缓存对象句柄)的属性 Name 和 Namespace 的值做 Hash 运算,即对于 SQL 来说是基于属性 Name 对应的该 SQL 的 SQL文本 和属性 Namespace 对应的常量 CRSR 做 Hash 运算
    2)根据得到的 Hash 值在Library Cache 的 Hash Table 中匹配是否有对应的 Hash Bucket
    3)在匹配到 Hash Bucket 之后,在这个 Hash Bucket 对应的 LCO handles(库缓存对象句柄链表)中寻找匹配的 LCO Handle(库缓存对象句柄),在SQL的过程中 LCO Handle 即 Parent Cursor 的句柄;这里需要检验 SQL文本 是否一致,因为不同的 SQL文本 计算出来的哈希值可能相同
    4)如果没有匹配到 LCO Handle,就意味着没找到对应的Parent Cursor,更没有对应的Child Cursor,也就意味着没有可以共享的解析树和执行计划,需要从头开始解析上述 目标SQL,新生成一个 Parent Cursor 和一个 Child Cursor,并挂在对应的 Hash Bucket 中,这就是硬解析
    5)如果有匹配到 LCO Handle,也就找到了这个 Handle 所指向的 LOC,即找到了匹配的 Parent Cursor,遍历这个 Parent Cursor 的 Child Tables 以查找满足重用的执行计划和解析树对应的 Child Cursor,这里需要对比涉及的对象定义、绑定变量类型和长度、优化器参数等
    6)如果有查找到满足条件的 Child Cursor,则直接重用该 Child Cursor 的执行计划和解析树等,不用再从头开始解析 目标SQL,这就是软解析
    7)如果没有没找到满足条件的 Child Cursor,就意味着没有可以共享的解析树和执行计划,需要从头开始解析上述 目标SQL,新生成一个 Child Cursor,并把这个 Child Cursor 挂在对应的 Parent Cursor 下,这也是硬解析

个人觉得讲的挺对的

Oracle数据库中的CURSOR分为两种类型:Shared Cursor 和 Session Cursor
1,Shared Cursor
Oracle里的第一种类型的Cursor就是Shared Cursor。 它是存在Shared Pool里,Shared Pool 是SGA里的里的一块内存区域,Shared Pool(Library Cache & Data Dict Cache)。 Library Cache缓存的是刚刚执行过的SQL语句和PL/SQL语句(procedure,function, package and trigger)所对应的执行计划,解析数(parse tree).Pcode,Mcode等对象。缓存在库缓存中的对象我们称它为库缓存对象(Library Cache Object). Oracle数据库中的Shared Cursor又细分为Parent Cursor(父游标)和Child Cursor(子游标). 这两种类型。我们可以通过查询V$SQLAREA和 V$SQL 来查看当前缓存中的Parent Cursor和 Child Cursor。其中V$SQLAREA用于查看Parent Cursor, V$SQL用于查看Child Cursor. 在ORACLE数据库里,任意一个目标SQL 一定会同时对应两个Shared Cursor,其中一个是Parent Cursor,另外一个是Child Cursor. Parent Cursor会存储该SQL 的SQL 文本,而该SQL 真正的可以被重用的解析数和执行计划则存储在Child Cursor中。
2.Session Cursor
Oracle里的第二种类型的Cursor就是Session Cursor。它是当前Session解析和执行SQL的载体,换句话说,Session Cursor用于在当前Session中的解析和执行SQL,它和Shared Cursor的区别是,它是缓存在PGA中,而不是像Shared Cursor那样缓存在SGA的库缓存里。
Session Cursor与Session是一一对应的,不同的session的Session Cursor直接没有办法共享,这个和Shared Cursor有本质的区别。Session Cursor是有生命周期的,每个session都在使用的过程中都至少会经历一场(open,parse,bind,execute,fetch and Close)中的一个或者多个阶段。用过的Session Cursor不一定缓存在对应的Session 的PGA中,这取决于Session_cached_cursor的值是否大于0.Oracle在解析和执行目标SQL时,会先去当前的SESSION的PGA中找是否有匹配的缓存的Session Cursor.当第一次解析和执行目标SQL时(显然是硬解析),当前SESSION的PGA中肯定不存在匹配的SESSION CURSOR,这个时候ORACLE 会新生成一个Session Cursor和一对Shared Cursor(即Parent Cursor 和 Child Cursor),这其中的Shared Cursor会存储能被所有Session共享,重用的内容(比如目标SQL的解析树,执行计划等),而Session Cursor则会经历一次open,parse,bind,execute,fetch和close中的一个或多个阶段。显然一个Session Cursor 只能对应一个Shared Cursor, 而一个Shared Cursor却可以同时对应多个Session Cursor.

硬解析:目标SQL第一次解析和执行,会同时生成Session Cursor和一对Shared Cursor(Parent Cursor and Child Cursor)

软解析:Session_Cached_Cursors=0,那么Session Cursor就会正常的执行Close操作,当上述的SQL再次重复执行时,是可以找到匹配的Shared Cursro但是找不到 Session Cursor了,这就意味着ORACLE 还必须为该SQL 新生成一个Session Cursor.

软软解析: Session_Cached_Cursor>0,那么满足一定的额外条件时,Oracle就不会对Session Cursor执行CLOSE操作,而是会将其标记为Soft Closed,同时将其缓存在当前的Session 的PGA中。这样做的好处是,当目标SQL 再次被重复执行时,此时的Shared Cursor 和Session Cursor都能匹配到。意味着ORACLE 不需要为该SQL 生成新的Session Cursor了,而是只需要从当前SESSION 的PGA中将之前已经标记为Soft Closed的匹配Session Cursor直接拿过来用就可以了。和软解析相比,此时ORACLE省掉了OPEN一个新的Session Cursor所需要耗费的资源和时间,另外,close 一个现有Session Cursor也不用做了(只需要把他标记为Soft Closed,同时将其缓存在当前的SESSION的PGA中就可以了),当然剩下的Parse, Bind,Execute,Fetch还是需要做的,这个过程就是软软解析。

总上所述,我们对Sesion Cursor和Shared Cursor之间的关联关系有如下总结:
无论是硬解析,软解析还是软软解析,ORACLE在解析和执行目标SQL时,始终会先去当前SESSION的PGA中寻找是否存在匹配的缓存Session Cursor.
1, 如果在当前SESSION 的PGA中找不到匹配的缓存Session Cursor, Oracle就会去库缓存中找是否存在匹配的Parent Cursor。如果找不到,Oracle就会新生成一个Session Cusor 和一对 Shared Cursor(Parent Cursor and Child Cursor),如果找到了匹配的Parent Cursor,但是找不到匹配的Child Cursor, Oracle就会去新生成一个Session Cursor和一个Child Cursor(这个Child Cursor会被挂在之前找到的匹配Parent Cursor下),无论哪一种情况,这两个过程对应的都是硬解析。

2, 如果在当前Session的PGA中找不到匹配的缓存 Session Cursor,但在库缓存中找到了匹配的Parent Cursor和Child Cursor,则Oracle会新生成一个Session Cursor并重用刚刚找到的匹配Parent Cursor和 Child Cursor,这个过程就是软解析。

3, 如果在当前Session的PGA中找到了匹配的缓存Session Cursor,此时就不再需要新生成一个Session Cursor,并且也不再需要向软解析那样得去库缓存中查找匹配的Parent Cursor了,因为ORACLE此时可以重用找到的匹配 Session Cursor,并可以通过这个Session Cursor直接访问到该SQL对应的Parent Cursor,这个过程就是软软解析。

参考:

自己理解
《DBA的思想天空》
https://blog.csdn.net/zq9017197/article/details/7345352/
https://www.cnblogs.com/youngerger/p/8572248.html
https://blog.csdn.net/guoxilen/article/details/79586648

  • 18
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汪灵骅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值