共享池部分-library cache、library cache object handle、library cache object、shared cursor、session cursor和解析

本文详细介绍了Oracle数据库中的SQL解析过程、软解析与硬解析的区别,以及shared pool、library cache、session cursor等核心组件的工作原理。文章还探讨了parent cursor与child cursor的概念,并解释了如何利用这些机制优化SQL执行效率。

共享池部分-library cache、library cache object handle、library cache object、shared cursor、session cursor和解析一些基本概念

关于cursor是oracle中开发人员经常使用的,这里我们不提开发人员所提的cursor,而是简单提下shared pool中的parent cursor和child cursor以及pga中的session cursor,以及硬解析、软解析、library cache的内部结构

  • shared pool中的library cache结构:
    1. library cache中的对象称为library cache object,而library cache object都是以library cache object handle的结构存储在library cache中,要访问library cache object,就需要先访问library cache object handle,library cache object handle就是oracle一种自定义的c语言复杂结构,那么oracle是如何来存储和访问library cache object handle

      实际上,library cache object handle是以hash table的方式存储在library cache中,每一个hash bucket都对应不同的hash value,对于单个hash bucket而言,里面存储的就是哈希值相同的所有library cache object handle,同一个hash bucket中不同的library cache object handle之间会用指针连接起来,即同一个hash bucket中不同的library cache object handle组成该hash bucket中涉及的library cache object的库缓存对象句柄链表(library cache object handles)。

  • oracle如何去解析sql语句、软解析和硬解析:
    1. 当oracle要执行目标sql语句时,首选对该sql的sql文本做hash运算,然后根据得到的hash值去相关的hash bucket中遍历对应的库缓存对象句柄链表,此时需要持有library cache latch,如果找到了对应的library cache object handle,则可以直接使用其执行计划、解析树等对象,最后释放library cache latch,这就是我们常说的软解析,如果没有找到对应的library cache object handle,需要再次持有library cache latch,由于有新增加的sql对应的shared cursor(parent cursor和child cursor)需要load到shared pool中,shared pool结构发生了变化,oracle需要在shared pool中加载和分配新的空间,oracle会在持有library cache latch的前提下再持有shared pool latch,成功申请空间后释放掉shared pool latch,然后重新解析sql并把相关的sql执行计划、解析树等对象以library cache object handle的方式存储到先关的hash bucket中的库缓存对象句柄链表中,最后再释放library cache latch,这个也就是凑名昭著的硬解析。

      查看上面软解析和硬解析的过程,我们发现硬解析会较长时间的持有library cache latch,也会持有shared pool latch,虽然软解析也会持有library cache latch,但是持有次数相比硬解析要少,持有时间也会硬解析短,软解析不会持有shared pool latch;如果系统出现大量的硬解析,则会引起library cache latch和shared pool latch的争用,一般在OLTP系统中,经常在书中看见要我们更多的使用绑定变量来提高系统的性能的原因,在oracle 11g后,oracle用mutex替换了相关的library cache latch,mutex的作用除了有latch的作用,还有library cache pin的作用。

  • 上面讲述了硬解析、软解析、library cache的结构后,再来简单提下经常看见parent cursor和child cursor
    1. 碰见太多的oracle文档中提到的shared pool主要是library cache和row cache,而library cache最主要的就是缓存sql语句,如果直接点就是缓存cursor,这里的cursor包括两种parent cursor和child cursor,那么parent cursor是什么了,child cursor又是什么了,这里需要对library cache object handle做一些深入的了解,library cache object handle也就是库缓存句柄有很多的属性,而对于cursor的library cache object handle而言比较重要的就是name、namespace和heap 0 pointer

      属性“Name”:表示的时library cache object handle所对应的library cache object的名称,例如如果是sql语句对应的库缓存对象句柄,则属性name就是该sql语句的sql文本;如果是表对应的库缓存对象句柄,则属性name就是该表的表明

      属性“Namespace“:表示的是库缓存对象句柄对应的库缓存对象所在的分组名,不同类型的库缓存对象句柄可能属于同一个分组,比如sql语句和pl/sql语句所对应的库缓存对象句柄的namespace值都是CRSR

      属性 “heap 0 pointer”:这里要说明下library cache object handle类似c语言的结构体,library cache object handle中还嵌套了一些子结构,其中heap 0 pointer是指向子结构heap 0的指针

      heap 0也是一种复杂的结构,它一样有很多属性,对于cursor而言比较重点的两个属性是tables和data block pointer。

      属性table记录的是于该heap 0所在的库缓存对象有关联关系的库缓存对象句柄地址的集合,table又细分为很多类,对于cursor而言重点关注child table,child table记录的就是从属于该heap 0所在的库缓存对象的子库缓存对象句柄地址的集合,简单来讲可以理解为指向子游标的库缓存对象句柄的指针,那么oracle就可以直接通过访问库缓存对象(parent cursor)句柄的heap 0中指定的child table,来直接找到相关的子库缓存对象(child cursor)句柄,进而访问子库缓存对象。
      属性data block pointer是heap 0存储的指向data heap的指针,data heap可以简单理解为库缓存中的一块连续的内存区域,而这些内存区域就是存储着cursor的动态运行时runtime数据,比如特别常见的执行计划、sql所涉及的对象定义、绑定变量类型和长度等。

  • parent cursor和child cursor都属于shared pool中shared cursor,parent cursor和child cursor都是以library cache object handle的方式存储在library cache中,parent cursor存储了目标sql的sql文本,其中sql文本是存储在parent cursor所对应的library cache object handle的属性name中,而child cursor则存储了执行计划和解析树。
    • oracle在解析目标sql去library cache中查找是否有匹配的shared cursor过程大体如下:

      • 1 首先是根据库缓存对象句柄的name和namespace做hash运算,由于sql语句和pl/sql语句的namespace都是crsr,对于sql和pl/sql语句可以直接理解为根据sql text来做hash运算,得到了hash value就去hash bucket中找到是否有匹配的hash bucket

        2 找到合适的hash bucket后,就去这个hash bucket对应的library cache object handles链表中找到是否有满足条件的library cache object handle(这里需要检验sql文本或者pl/sql文本是否一致,因为不同的sql语句或者pl/sql语句的hash value可能一致)

        3 根据找到的library cache object handle也就是parent cursor对应的库缓存对象句柄去找对应的child cursor,最后看是否满足重用执行计划和解析数(要比对对象、绑定变量类型和长度等)

    • parent cursor和child cursor遍历顺序:
      1. child cursor的name属性是空的,也就是我们不可能直接脱离parent cursor而去寻找child cursor,查看sql是否可以重用时都是需要先找到parent cursor然后根据parent cursor对应的库缓存对象句柄中heap 0 pointer-heap 0-table-child tables来去cursor cursor对应的库缓存对象句柄链表中去遍历是否有满足的cursor child(此时不仅仅需要验证sql文本一致,文本一致只作用于验证parent cursor部分是否可以共享,还要查看sql所涉及的对象定义、绑定变量类型和长度、优化器参数等来看是否能够重用child cursor)

        那么对于shared pool而言硬解析就有以下两种情况: 1 parent cursor和child cursor都没有办法共享 2 parent cursor能够共享,但是child cursor不能共享

        可能在刚开始我们第一次接触oracle部分书籍和文档时就提到了shared pool中的library cache,但是真正能够讲清楚shared cursor、child cursor、hash bucket、library cache、library cache object、软解析、硬解析得并不多,当然这些概念模棱两可并不太影响我们运维的工作,但是如果能真正理解这些概念是可以帮助我们更深入的理解oracle的sql解析部分

    • 下面再来简单讲一个比较边缘化的概念session cursor:
      1. session cursor顾名思义就是session级别的cursor,和shared cursor一样,session cursor也是oracle定义的一种c语言复杂结构,也是以hash表的方式缓存起来,所不同的是session cursor是缓存在PGA中。

        跟shared cursor所不同的还是有以下几点:

        • 1 session cursor是于session相对应,不同的session之间的session cursor没有办法共享
          2 session cursor也是有生命周期的
          3 session cursor也是以hash表的形式缓存在pga中,oracle也是通过相关的hash运算先访问当前session的pga的session cursor。

        由于session cursor概念的引入,oracle的解析需要增加这一步骤:首先计算hash value查找session cursor中是否有满足条件的session cursor,如果有满足条件的session cursor,则重用这个session cursor,如果没有满足条件的session cursor,则需要重新生成一个session cursor,对于session cursor而言,这个也属于硬解析,如果session cursor、parent cursor、child cursor都已经分别存在了PGA和library cache中,则这就是我们所提到的软软解析,软软解析不需要再次生成session cursor,相比软解析消耗更少的资源和时间。

    • 软软解析的必须条件:
      1. 软软解析需要shared cursor和session cursor都分别在shared pool和pga中缓存,而将session cursor缓存到pga跟sql的执行解析次数和session_cached_cursors参数有关:如果session_cached_cursors等于0,那么session cursor在open、parse、bind、execute fetch后就直接close了。而如果session_cached_cursor大于0,而且session cursor所对应的sql解析和执行次数超过了3次,这个session cursor就能够被pga缓存住(存储在pga中的session cursor是用lru算法来管理的),这样sql再次执行时,shared cusror和session cursor都能够找到匹配的记录,oracle不再重复的需要为其生成一个session cursor,当然close一个缓存在pga的session cursor,也只是需要将其标记为soft cloud。

      接下来我们来验证下session cursor缓存到pga的条件:

      SQL> show parameter session_cached_cursors;

      NAME                                 TYPE        VALUE
      ------------------------------------ ----------- ------------------------------
      session_cached_cursors               integer     50

      SQL> select count(*) from t_samp01;

        COUNT(*)
      ----------
               0

      SQL> select cursor_type,sql_id from v$open_cursor where sid=50 and sql_text like 'select count(*) from t_samp01%';

      no rows selected

      SQL> select count(*) from t_samp01;

        COUNT(*)
      ----------
               0

      SQL> select cursor_type,sql_id from v$open_cursor where sid=50 and sql_text like 'select count(*) from t_samp01%';

      no rows selected

      SQL> select count(*) from t_samp01;

        COUNT(*)
      ----------
               0

      SQL> select cursor_type,sql_id from v$open_cursor where sid=50 and sql_text like 'select count(*) from t_samp01%';

      CURSOR_TYPE                                                      SQL_ID
      ---------------------------------------------------------------- -------------
      DICTIONARY LOOKUP CURSOR CACHED                                  16099tj19y4gr

      SQL> select count(*) from t_samp01;

        COUNT(*)
      ----------
               0

      SQL> select cursor_type,sql_id from v$open_cursor where sid=50 and sql_text like 'select count(*) from t_samp01%';

      CURSOR_TYPE                                                      SQL_ID
      ---------------------------------------------------------------- -------------
      SESSION CURSOR CACHED                                            16099tj19y4gr
      SQL> select sql_text from v$sql where sql_id='16099tj19y4gr';

      SQL_TEXT
      --------------------------------------------------------------------------------
      select count(*) from t_samp01

      看见同一个session下执行3次以上的sql对应的session cursor已经缓存到了pga中

      在oracle 11g之前的办法,在缓存session cursor的hash表对应的hash bucket中,oracle会缓存目标sql对应的parent cursor的库缓存对象句柄地址,这意味着oracle已经建立起了session cursor到parent cursor的联系,这样软软解析会对相关的latch的争用更低,因为session cursor中存储了直接指向parent cursor的指针,oracle不再需要和软解析一样要去持有library cache latch访问相关的hash bucket的library cache object handles链表中查找匹配的parent cursor

      在oracle 11g后,dump session的信息,session cursor中已经没有记录,对应的parent cursor的library cache object handle地址:
      11.2.0.3版本下alter sssion set events ‘immediate trace name errorstack level 3’的trac文件session cached cursor的dump中已经不存储指向parent cursor中的library cache object handle地址

      11.2.0.3版本的trace文件:
      ----- Session Cached Cursor Dump -----
      ----- Generic Session Cached Cursor Dump -----
      -----------------------------------------------------------
      -------------- Generic Session Cached Cursors Dump --------
      -----------------------------------------------------------
      hash table=0x7feac43941d0 cnt=6 LRU=0x7feac4386678 cnt=6 hit=10 max=50 NumberOfTypes=6
      type#0 name=DICTION count=0
      type#1 name=BUNDLE  count=5
      type#2 name=SESSION count=1
      type#3 name=PL/SQL  count=0
      type#4 name=CONSTRA count=0
      type#5 name=REPLICA count=0
       Bucket#024 seg=0x7feac4394648 nit=5 nal=5 ips=5 sz=56 flg=3 ucnt=1
         0 cob=0x7feac43021f8 idx=18 flg=0 typ=1 cur=0x7feac4302328 lru=1 fl=15
       Bucket#056 seg=0x7feac4394c48 nit=5 nal=5 ips=5 sz=56 flg=3 ucnt=1
         0 cob=0x7feac42db1e8 idx=38 flg=0 typ=1 cur=0x7feac42db318 lru=1 fl=15
       Bucket#130 seg=0x7feac4395a28 nit=5 nal=5 ips=5 sz=56 flg=3 ucnt=1
         0 cob=0x7feac43a1f78 idx=82 flg=0 typ=1 cur=0x7feac43a20a8 lru=1 fl=15
       Bucket#183 seg=0x7feac4396418 nit=5 nal=5 ips=5 sz=56 flg=3 ucnt=1
         0 cob=0x7feac43abcd8 idx=b7 flg=0 typ=1 cur=0x7feac43abe08 lru=1 fl=15
       Bucket#187 seg=0x7feac43964d8 nit=5 nal=5 ips=5 sz=56 flg=3 ucnt=1
         0 cob=0x7feac43ac3f8 idx=bb flg=0 typ=1 cur=0x7feac43ac528 lru=1 fl=15
       Bucket#192 seg=0x7feac43965c8 nit=5 nal=5 ips=5 sz=56 flg=3 ucnt=1
         0 cob=0x7feac43043b8 idx=c0 flg=0 typ=2 cur=0x7feac43027b0 lru=1 fl=1
      。。。
      10g的版本trace文件:
      这里会记录hdl就是session对应的library cache object handle的地址。
      Session cached cursors
      -----------------------------------------------------------
      -------------- Generic Session Cached Cursors Dump --------
      -----------------------------------------------------------
      hash table=0xb7f31d00 cnt=3 LRU=0xb7f273f8 cnt=3 hit=4 max=20 NumberOfTypes=3
      type#0 name=KQD     count=1
      type#1 name=KQD BUN count=0
      type#2 name=KKS     count=2
       Bucket#056 seg=0xb7f323f4 nit=4 nal=4 ips=4 sz=16 flg=3 ucnt=1
         0 cob=0xb7f39d80 38 flg=0 typ=0 idx=38 cur=0xb7f39b9c lru=1 flg=5 hdl=0x34cb963c
         1 cob=0xb7f39d90 0 flg=0 typ=0 idx=0 cur=(nil) lru=0 flg=0 hdl=(nil)
         2 cob=0xb7f39da0 0 flg=0 typ=0 idx=0 cur=(nil) lru=0 flg=0 hdl=(nil)
         3 cob=0xb7f39db0 0 flg=0 typ=0 idx=0 cur=(nil) lru=0 flg=0 hdl=(nil)
       Bucket#168 seg=0xb7f331f4 nit=4 nal=4 ips=4 sz=16 flg=3 ucnt=1
         0 cob=0xb7f3b02c a8 flg=0 typ=2 idx=a8 cur=0xb7f4e2c0 lru=1 flg=1 hdl=0x34d8a490
         1 cob=0xb7f3b03c 0 flg=0 typ=0 idx=0 cur=(nil) lru=0 flg=0 hdl=(nil)
         2 cob=0xb7f3b04c 0 flg=0 typ=0 idx=0 cur=(nil) lru=0 flg=0 hdl=(nil)
         3 cob=0xb7f3b05c 0 flg=0 typ=0 idx=0 cur=(nil) lru=0 flg=0 hdl=(nil)
       Bucket#205 seg=0xb7f33694 nit=4 nal=4 ips=4 sz=16 flg=3 ucnt=1
         0 cob=0xb7f3b0fc cd flg=0 typ=2 idx=cd cur=0xb7f3b1b8 lru=1 flg=1 hdl=0x347beec8
         1 cob=0xb7f3b10c 0 flg=0 typ=0 idx=0 cur=(nil) lru=0 flg=0 hdl=(nil)
         2 cob=0xb7f3b11c 0 flg=0 typ=0 idx=0 cur=(nil) lru=0 flg=0 hdl=(nil)
         3 cob=0xb7f3b12c 0 flg=0 typ=0 idx=0 cur=(nil) lru=0 flg=0 hdl=(nil)
    • 还有一个参数cursor_space_for_time,该参数是为了缓解发生在child cursor上的与库缓存相关的latch争用,但是在oracle11GR1开始,mutex已经替代了各种与库缓存对象相关的latch,所以cursor_space_for_time参数在oracle 11.1.0.7及其后续的版本中已经过时。
      1. oracle在解析执行sql时首先需要先获取库缓存相关的latch,然后再持有相关的cursor的library cache pin这个enqueue来pin住cursor,在sql执行完毕后oracle就会释放掉这个library cache pin,也就是相关的library cache对象会被置换出library cache,而如果有一个场景是:一个session cursor只会open和close一次,但是与之先关的child cursor中间会反复经历parse、bind、execution和fetch阶段,这样如果每次执行完毕后都需要反复的获取库缓存对象的latch和library cache pin,这样就会造成库缓存的latch争用。

        注意:解析执行sql时首先获取library cache latch,在执行sql时为了防止sql对应的cursor被修改,则需要将这个sql相关的library cache对象pin到内存中,这个过程是持有library cache pin的过程,而在oracle11g后,持有library cache latch和library cache pin的过程已经被mutex所代替。

        cursor_space_for_time参数可以一定程度的解决库缓存的latch争用,当将此参数设置为true时,sql执行完毕后oracle也不会释放掉该sql相关的library cache pin,而是要等待游标关闭后才会释放掉相关sql的library cache pin,但是由于部分执行完毕的sql对应的child cursor并不能马上被age out出shared pool,从而导致shared pool的空间压力。

    • 下面简单的摘要一部分官方文档中对这个参数的描述
      1. true

        Shared SQL areas are kept pinned in the shared pool. As a result, shared SQL areas are not aged out of the pool as long as an open cursor references them. Because each active cursor’s SQL area is present in memory, execution is faster. However, the shared SQL areas never leave memory while they are in use. Therefore, you should set this parameter to true only when the shared pool is large enough to hold all open cursors simultaneously.

        In addition, a setting of true retains the private SQL area allocated for each cursor between executions instead of discarding it after cursor execution, saving cursor allocation and initialization time.

        false
        Shared SQL areas can be deallocated from the library cache to make room for new SQL statements.

      shared pool的内部结构远远比上面所列的要复杂,对于有些概念xiaoyu也不是理解的非常清晰,有兴趣的可以去看看相应的DSI部分。

内容概要:本文围绕“基于多面体聚合与闵可夫斯基的电动汽车可调能力评估研究”展开,系统提出一种基于多面体建模与几何运算的聚合方法,用于量化大规模电动汽车集群的可调节能力。通过构建单车充电可行域的凸多面体表示,并利用闵可夫斯基实现群体调控潜力的数学聚合,形成统一的等效灵活资源集合,从而精确刻画电动汽车集群在时间与功率维度上的整体调节边界。该方法结合Matlab代码实现,支持对聚合结果的可视化呈现与边界分析,为电力系统中的需求响应、虚拟电厂运营及分布式能源调度提供了高精度建模工具。研究强调科研应兼顾严谨逻辑与创新思维,倡导借助YALMIP等优化工具提升建模效率与求解可靠性。; 适合人群:具备电力系统分析、凸优化理论或运筹学背景,从事新能源并网、电动汽车调度、综合能源系统等方向的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握多面体建模与闵可夫斯基在电力系统灵活性聚合中的数学原理与实现方法;②学习利用Matlab完成电动汽车集群可调能力的建模、聚合与可视化分析;③应用于虚拟电厂资源聚合、需求响应潜力评估、配电网柔性负荷调控等实际场景的建模与优化决策。; 阅读建议:建议读者结合文中Matlab代码逐模块复现算法流程,重点理解多面体定义、约束处理及闵可夫斯基的近似计算实现,同时参考提供的YALMIP工具包资源,深入掌握优化建模技巧,以全面提升对复杂系统聚合建模的能力。
内容概要:本文系统研究了基于Wasserstein生成对抗网络(W-GAN)的光伏出力场景生成方法,旨在应对新能源出力的高度不确定性。相较于传统GAN,W-GAN通过引入Wasserstein距离与梯度惩罚机制,显著提升了模型训练的稳定性与生成数据的质量,能够更精确地捕捉光伏功率时序数据的波动性与时序相关性。研究详细阐述了模型架构设计、损失函数构建、梯度惩罚项(GP)的实现细节,并通过Python代码实现了完整的数据预处理、模型训练、场景生成与后评估流程。生成的高保真光伏场景在统计特性(如分布形态、波动幅度、日内趋势)上与真实数据高度吻合,有效满足了电力系统对不确定性建模的严苛要求。; 适合人群:具备Python编程能力深度学习基础知识,从事新能源发电预测、电力系统规划、运行调度、储能配置及风险管理等领域的研究生、科研人员工程技术人员。; 使用场景及目标:①为含高比例光伏的电力系统进行可靠性评估、优化调度与安全校核提供高质量、多样化的输入场景;②支撑储能系统容量配置、需求响应策略制定等决策,以应对光伏出力的波动性;③作为深度学习在能源领域应用的典型案例,服务于相关课题的教学、科研与项目开发。; 阅读建议:建议读者深入研读并运行所提供的Python代码,重点关注W-GAN中判别器(Critic)的构造、梯度惩罚项的编码实现以及训练过程中的超参数(如学习率、惩罚系数)调优策略,可通过对比生成场景与真实场景的可视化结果来评估模型性能,并尝试将其扩展至条件W-GAN(CW-GAN)以生成特定气象条件下的光伏场景。
内容概要:本文围绕基于生成对抗网络(GAN)与Wasserstein GAN(W-GAN)的光伏场景生成展开研究,重点介绍如何利用Python代码实现W-GAN模型,以生成高质量、高稳定性的光伏发电出力场景数据。相较于传统GAN,W-GAN通过引入Wasserstein距离梯度惩罚机制,有效缓解了训练过程中的模式崩溃与梯度消失问题,显著提升了生成数据的真实性多样性。该方法在新能源出力不确定性建模、电力系统仿真分析等领域具有重要应用价值。文中提供了完整的实现流程,涵盖数据预处理、网络结构设计、损失函数构建、模型训练优化及生成结果可视化等关键环节。; 适合人群:具备一定Python编程能力深度学习基础,从事新能源发电预测、电力系统规划、智能电网仿真或人工智能算法应用等相关方向的研究人员及高校研究生。; 使用场景及目标:①用于构建高精度的光伏出力不确定性场景集,支撑电力系统调度决策、储能配置与风险评估;②为高比例可再生能源接入下的电力系统提供可靠、多样化的输入场景,提升仿真与优化模型的鲁棒性;③帮助研究者深入理解W-GAN的理论机制与工程实现,推动其在能源系统建模中的创新应用。; 阅读建议:建议读者结合提供的代码进行动手实践,重点关注判别器与生成器的网络架构设计、Wasserstein损失函数的实现方式以及梯度惩罚项的添加技巧,同时可在不同气候区域或时间尺度的光伏数据集上进行迁移实验,进一步验证模型泛化能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值