• sga之library cache 内部原理


    一、概述

    library cache(库缓存)是shared pool中的一块内存区域,它的主要作用是缓存刚刚执行过的sql语句和pl/sql(包括存储过程、包、函数、触发器)所对应的解析计划、解析树等对象,当同样的sql或pl/sql再次被执行时,就可以直接利用在library cache中的那些相关对象,而无需再次从头开始解析,这样提高了这些语句的执行效率。
            查看library cache在内存中的位置。

     
       

       

          缓存在library cache中的对象我们称之为库缓存对象(library cache object),所有的库缓存对象都是以库缓存对象句柄(library cache object handle)的结构存储在library cache中,oracle通过访问库缓存对象句柄来访问库缓存对象。

         库缓存对象句柄是oracle自定义的一种c语言复杂结构,它是以hash table的方式存储在library cache中的,这意味着oracle会通过hash运算来存储和访问对应的库缓存对象句柄。

         下图为从hash角度分析库缓存的构成:

            
          由上图可看出,整个library cache可以看作是一组由hash bucket所组成,每一个hash bucket所对应的不同的哈希值。对于单个bucket而言,里面存储的就是哈希值相同的所有库缓存对象句柄,同一个hash bucket中不同的库缓存对象句柄之间会用指针链接起来,即同一个hash bucket中不同的库缓存对象句柄之间实际上组成了一个库缓存对象句柄链表(library cache object handles)。一个library handle管理着一个libirary cache object(lco),handle对实际的lco起到元数据和指针作用,lco保存着实际信息。

        当运行select * from employees时,oracle会计算sql文本的哈希值,以此寻找相关的hash bucket,遍历库缓存对象句柄链表,如果能找到则可直接使用解析计划、解析树等信息,若找不到,则需要从头开始解析,生成解析树、解析计划等并存储在library cache object handle中。


        library cache object handle结构图:

                 

          库缓存对象句柄有name、namespace等属性组成,着重分析name、namespace、heap 0这三个属性。

          属性“name”表示库缓存对象句柄所对应的库缓存对象名称。例如如果是sql语句对应的库缓存对象句柄,则属性name就是该sql语句的sql文本;如果是表对应的库缓存对象句柄,则属性name就是该表的表名。

          属性“namespace” 表示的是库缓存对象句柄对应的库缓存对象所在的分组名,不同类型的库缓存对象句柄可能属于同一个分组。

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


        在library cache中,bucket初始化的数量受隐藏参数 _kgl_bucket_count参数控制。

             

    值为9,则理论上应分配2^9*256=131072个bucket.


    通过library cache dump可发现,bucket为131072。在library cache dump中,size为Buckest的数量,count为Object Handles的数量。

            

    heap 0 pointer(一说为heap 0 object)就是指向子结构heap 0的指针,heap 0 的结构如下:

    heap 0 也是一种复杂的结构,它有很多属性,

    tables属性:记录的是与该heap 0所在的库缓存对象有关的库传讯对象句柄地址集合。Tables分为许多细类。

    Data blocks属性。

     二、dump验证

          分别以sys用户和test用户创建一张一摸一样的表。

    SQL> show user

    USER is "SYS"

    SQL> create table t as select * from v$mystat;

    Table created.

    另起一个连接,用数据库用户test登录

    SQL> show user

    USER is "TEST"

    SQL> create table t as select * from v$mystat;

    Table created.

    以俩个用户为基础分别执行select * from t where t.STATISTIC#=671;

     
       

            查询该sql的sql_id和hash_value

            
                

        执行library cache dump

    SQL> alter session set events 'immediate trace name library_cache level 10';

    Session altered.


    通过sql_id或hash value查询dump, 可在dump中找到关于该sql的内容,如下图
            

    以上图为例分析library cache结构

    Bucket: #=114283 Mutex=0x9bdc28e8(0, 20, 0, 6)

      LibraryHandle:  Address=0x84e5fb00 Hash=cb15be6b LockMode=N PinMode=0 LoadLockMode=0 Status=VALD

     --bucket号,Hash=cb15be6b此处采用的是16进制,转换为十进制的值为3407199851,正好与上面v$sqltext中查出来的值一致。

    ObjectName:  Name=select * from t where t.STATISTIC#=671

    --object 的名称 即上面说过的name属性,也就是lco(library cache objects)

    FullHashValue=9581b1f4c50e25f2e8500930da5a0101 Namespace=SQL AREA(00) Type=CURSOR(00) Identifier=0 OwnerIdn=0

    --上面说过的namespace,尚不太清楚fullhashvalue的含义

    ChildTable:  size='16'

    Child:  id='0' Table=0x87b03f60 Reference=0x87b039c8 Handle=0x98efe438

    Child:  id='1' Table=0x87b03f60 Reference=0x87b03d10 Handle=0x83595530

    --俩个child cursor

    参考文档:崔华《基于oracle的sql优化》

  • 相关阅读:
    Sql语句中IN和exists的区别及应用
    时间戳/Date(1354116249000)/ 转换
    SqlServer不允许更改字段类型(表中已有数据)
    Firefox内存占用过高解决方法
    接口开发中的测试问题
    c# winform 窗体起始位置 设置
    【整理】C#文件操作大全(SamWang)
    C#实现JSON序列化与反序列化
    解决方案资源管理器中跟踪活动项
    C#中方法的参数的四种类型
  • 原文地址:https://www.cnblogs.com/youngerger/p/8508564.html
Copyright © 2020-2023  润新知