ITPub博客

首页 > Linux操作系统 > Linux操作系统 > shared pool

shared pool

原创 Linux操作系统 作者:yuecaibo 时间:2012-03-04 10:13:03 0 删除 编辑
shared pool
 共享池,存放SQL和PLSQL解析树和字典对象定义的共享区域
 他又分为两部分:
 1.data dict cache 也叫rowcache 加速SQL的解析
   使用过的字典 就会缓存在这里 再次使用这个字典就直接从内存获取
   这些统计的信息在 v$rowcache中记录
      
   DC_USERS   用户列表
   DC_PRIVS   权限列表
   DC_TABLES 表的列表
   DC_COLUMNS 某表的字段列表
 
  SQL> alter system flush shared_pool;
  System altered.
  SQL> select PARAMETER,COUNT,USAGE from v$rowcache where count <> 0;
  PARAMETER         COUNT  USAGE
  -------------------------------- ---------- ----------
  dc_tablespaces      1      1
  dc_users      1      1
  dc_rollback_segments    22     22
  dc_objects     75     75
  dc_object_ids     74     74
  dc_histogram_defs   181    181
  dc_histogram_data   108    108
  dc_histogram_data    29     29
  8 rows selected.
  SQL> select * from scott.emp where 0=1;
  no rows selected
  SQL> select PARAMETER,COUNT,USAGE from v$rowcache where count <> 0;
  PARAMETER         COUNT  USAGE
  -------------------------------- ---------- ----------
  dc_segments      4      4
  dc_tablespaces      1      1
  dc_users      1      1
  dc_rollback_segments    22     22
  dc_objects     82     82
  dc_object_ids     92     92
  dc_usernames      1      1
  dc_histogram_defs   258    258
  dc_histogram_data   126    126
  dc_histogram_data    29     29
  10 rows selected.
  SQL>
 2.library cache: 存储最近频繁执行的SQL或PLSQL语句信息 加速解析 减少语句重解析
 主要包括两部分共享SQL AREA和共享PL/SQL AREA
 共享SQL AREA :
  LIBRARY CACHE的核心部分是SQL AREA,它存放了执行计划和解析树,SQL必须文本匹配才可以共享,它包括:
  SQL 语句文本
  分析树语句的已编译版本
  执行计划执行时要采取的步骤
 共享PL/SQL AREA:
  存放编译代码,调试代码,解析树等信息
  另外会存在控制部分,如LRU列表。
 
 Library Cache 中包括共享SQL 区(Shared SQL Areas)、PL/SQL 存储过程和包以及控制结构(如锁、库缓存句柄)
 任何用户都可以访问共享SQL区,获取已经执行过的相同SQL的解析信息
 这部分信息也是使用LUR算法来管理的.
 
 
 ORACLE提供一个共享SQL 区(Shared SQL Areas)和私有SQL 区(Private SQL Areas 属于PGA)。
 共享SQL区包含着已经执行过的SQL文本,解析树,执行计划等信息
 私有SQL区包含了绑定变量值和运行时期内存结构信息等数据。
 
 Oracle 会为每一条SQL 语句运行(每运行一条语句Oracle 都会打开一个游标)
 当发现两个(或多个)用户都在运行同一SQL 语句时,Oracle 会重新组织SQL 区,
 使这些用户能重用共享SQL 区。但他们还会在私有SQL 区中保存一份这条SQL 语句的拷贝。
 Oracle 通过为SQL 语句使用同一共享SQL区多次运行来节省内存和减少解析语句带来的昂贵代价.
 
 当一条新的SQL 语句被解析时,Oracle 从共享池中分配一块内存来存储共享SQL 区。
 这块内存的大小与这条语句的复杂性相关。
 如果Shared Pool 不够空间分配给共享SQL区,Oracle 将释放从LRU 链表中查找到最近最少使用的内存块,
 直到有足够空间给新的语句的共享SQL区。
 如果Oracle 释放的是一个共享SQL 区的内存,那么相同的语句在下次执行时需要再次解析并重新分配共享SQL 区。
 oracle在library cache中找不到的sql就认为是从来没执行过
 
 每一个运行SQL语句的会话都有一个私有SQL区。
 所有提交了相同SQL语句的用户都有各自的私有SQL区,并且他们共享一个共享SQL区。
 因此,一个共享SQL区可能和多个私有共享区相关联
 
 要了解library cache 必须先了解SQL执行过程
 SQL执行过程:
   一.探查执行历史
   二.分析语句
   三.HASH值匹配
   四.生成执行计划
   五.执行语句
   六.排序获取返回行
 
  
 一.探查执行历史 
  1.检查是否有打开的游标,如果有,直接通过游标连接到位于PGA的private_sql_area
  2.检查初始化参数SESSION_CACHED_CURSORS是否被设置
    如果设置,则同样可以通过游标指向到PGA的private_sql_area
  oracle会按上面的顺序逐次检查,当发现满足条件时,就直接执行SQL(转11步),这种解析就叫快解析或软软解析
 二.分析语句
  如果上面的探查历史失败,就要走这步
  4.创建一个游标
  5.语法检查Syntax Check:
   检查语法书写是否正确,是否符合SQL Reference Manual中给出的SQL语法。
  6.语义分析Semantic Analysis:
   查找数据字典,检查表、列是否正确,检查在对象上标记锁,如果和要放置的锁冲突则等待或报错.
   锁得目的就是使得在语句的语法分析过程中不改变这些对象的定义,
   验证为存取所涉及的模式对象所需的权限是否满足。
 三.HASH值匹配
  7.将语句转化成ASCII等效数字码,再通过HASH算法得到散列值。
  8.检查库缓存中是否存在同样hash值的语句。
    如果存在,要再次检查对象和权限的(若和以缓存的SQL对象权限等不匹配,会生成子游标).执行SQL(转11步),这种解析就叫软解析
 四.生成执行计划
  如果上面的HASH值匹配失败,就要走这步,经历这步就叫硬解析
  9.由优化器(CBO)对SQL语句生成解析树,再对语句引用的表和列进行分析,得出若干种执行计划,从中选择一种最优的.
    这步是最消耗资源的.
  10.记录这条SQL,及其解析树,执行计划,父游标和子游标等信息记录到v$sql v$sqlarea
 五.执行语句
  11.执行语句从DB buffer cache中获取数据
  12.若数据不在DB buffer cache中,就要先把所需数据文件中读入
   如果DB bufferc cache没有空间加载 就要通过LRU算法来清理
   数据是从 db_buffer_cache 获取已存在的数据 就叫逻辑读
   数据若不在db_buffer_cache,从磁盘加载 就叫物理读
 六.排序获取返回行 如果语句有返回行给用户才有此步骤,返回的方式是分批分量的.
  13.如果语句包含order by或其他需要排序的语法(max minus等)
    要在sort_area_size里排序 它存在于PGA中(只在这里排序 就是内存排序)
  14.如果排序量很大 sort_area_size容不下就去临时表空间去做排序(就是磁盘排序)
  15.如果排序需要返回给用户,将排好的数据放入sort_area_retained_size 它存在于UGA中
   排序是批量返回的,比如100行,全部排好后,将前20就放入这个空间,被取走后 再放入20...
   
 
     内存游标
   library cache里面有内存游标 和PLSQL游标不同,这个游标是个可执行对象 
   这个游标分为父游标和子游标
   一个相同文本的SQL产生一个父游标
   父游标主要存储的是SQL文本的HASH值
   子游标主要存储SQL的执行计划和解析树
       
   v$sqlarea保存的是父游标的sql信息,而v$sql保存的是子游标的sql的信息。
   在v$sqlarea里面有一列VERSION_COUNT字段,
    其中代表的就是对于此父游标的子游标的数量,
    也就是在v$sql里面的子游标的sql记录的数量。
   在v$sql中有一列CHILD_NUMBER字段,表示该子游标的编号。
   可以说v$sqlarea和v$sql是一对多的父子关系。
   一般情况下父游标不会被交换出内存 子游标会被交换出内存 所以我们应该控制子游标的数量
   
   游标是共享的
   sql语句执行时会将SQL文本通过hash算法生成一个散列值
   就拿着这个散列值去library cache查询是否有相同的散列值
   如果存在 说明历史上SQL执行过 就直接拿到执行计划去执行了
   但共享是有条件的
    一个父游标至少有一个子游标
   为什么说至少有一个?
    相同SQL文本产生的HASH值相同 说明他们的父游标相同
    但这并不足以说明就能使用同一个子游标
    因为相同文本会有不同对象的情况
搭建实验环境
SQL> create user u1 identified by u1;
User created.
SQL> create user u2 identified by u2;
User created.
SQL> create user u3 identified by u3;
User created.
SQL> grant connect,resource to u1,u2,u3;
Grant succeeded.
SQL> grant create public synonym to u3;
Grant succeeded.
SQL> conn u1/u1
Connected.
SQL> create table emp (x number);
Table created.
SQL>
SQL> conn u2/u2
Connected.
SQL> create table emp(p number);
Table created.
SQL>
SQL> grant select on emp to u3;
Grant succeeded.
SQL>
SQL> conn u3/u3
Connected.
SQL> create public synonym emp for u2.emp;
Synonym created.
SQL>
SQL> alter system flush shared_pool;
System altered.
SQL>
测试
SQL> conn u1/u1
Connected.
SQL> select * from emp;
no rows selected
SQL> conn / as sysdba
Connected.
SQL> col sql_text for a28
查看父游标信息
SQL> select EXECUTIONS,ADDRESS,HASH_VALUE,SQL_TEXT from v$sqlarea where lower(sql_text) like 'select * from emp%';
EXECUTIONS ADDRESS  HASH_VALUE SQL_TEXT
---------- -------- ---------- ----------------------------
  1 2D26F394 1745700775 select * from emp
SQL>
查看子游标信息
SQL> select EXECUTIONS,ADDRESS,HASH_VALUE,SQL_TEXT from v$sql where lower(sql_text) like 'select * from emp%';
EXECUTIONS ADDRESS  HASH_VALUE SQL_TEXT
---------- -------- ---------- ----------------------------
  1 2D26F394 1745700775 select * from emp
SQL>
SQL> conn u2/u2
Connected.
SQL> select * from emp;
no rows selected
SQL> conn / as sysdba
Connected.
SQL>
再查看父游标被执行了两次 因为SQL文本相同
SQL> select EXECUTIONS,ADDRESS,HASH_VALUE,SQL_TEXT from v$sqlarea where lower(sql_text) like 'select * from emp%';
EXECUTIONS ADDRESS  HASH_VALUE SQL_TEXT
---------- -------- ---------- ----------------------------
  2 2D26F394 1745700775 select * from emp
再看子游标 因为对象不同 所以是两个 重新解析产生了一个新的执行计划
SQL> select EXECUTIONS,ADDRESS,HASH_VALUE,SQL_TEXT from v$sql where lower(sql_text) like 'select * from emp%';
EXECUTIONS ADDRESS  HASH_VALUE SQL_TEXT
---------- -------- ---------- ----------------------------
  1 2D26F394 1745700775 select * from emp
  1 2D26F394 1745700775 select * from emp
SQL>
SQL> conn u3/u3
Connected.
SQL> select * from emp;
no rows selected
SQL> conn / as sysdba
Connected.
SQL> select EXECUTIONS,ADDRESS,HASH_VALUE,SQL_TEXT from v$sqlarea where lower(sql_text) like 'select * from emp%';
EXECUTIONS ADDRESS  HASH_VALUE SQL_TEXT
---------- -------- ---------- ----------------------------
  3 2D26F394 1745700775 select * from emp
SQL>
SQL> select EXECUTIONS,ADDRESS,HASH_VALUE,SQL_TEXT from v$sql where lower(sql_text) like 'select * from emp%';
EXECUTIONS ADDRESS  HASH_VALUE SQL_TEXT
---------- -------- ---------- ----------------------------
  1 2D26F394 1745700775 select * from emp
  2 2D26F394 1745700775 select * from emp
SQL>

所以对我们来说 保持SQL语句数据一致性很重要 共享SQL很重要
但有时开发写的SQL不尽人意 一定要让开发人员写SQL时使用绑定变量
绑定变量
SQL> select ename from emp where empno=7788;
SQL> select ename from emp where empno=7369;
这样的两条SQL 我们必须要让它实现共享 减少硬解析 节省内存资源
方法是使用绑定变量
SQL> conn / as sysdba
Connected.
SQL> alter system flush shared_pool;
System altered.
SQL> conn scott/seker
Connected.
SQL>
SQL>
    declare
    v_eno number := 7788;
    v_ename varchar2(20);
    begin
    select ename into v_ename from emp where empno=v_eno;
    end;
SQL> /
PL/SQL procedure successfully completed.
SQL>
    declare
    v_eno number := 7369;
    v_ename varchar2(20);
    begin
    select ename into v_ename from emp where empno=v_eno;
   end;
SQL> /
PL/SQL procedure successfully completed.
SQL>
SQL> conn / as sysdba
Connected.
SQL> select EXECUTIONS,ADDRESS,HASH_VALUE,SQL_TEXT from v$sqlarea where lower(sql_text) like 'select ename%';
EXECUTIONS ADDRESS  HASH_VALUE SQL_TEXT
---------- -------- ---------- ----------------------------
  2 2D285838 1426374283 SELECT ENAME FROM EMP WHERE
          EMPNO=:B1

SQL> select EXECUTIONS,ADDRESS,HASH_VALUE,SQL_TEXT from v$sql where lower(sql_text) like 'select ename%';
EXECUTIONS ADDRESS  HASH_VALUE SQL_TEXT
---------- -------- ---------- ----------------------------
  2 2D285838 1426374283 SELECT ENAME FROM EMP WHERE
          EMPNO=:B1

SQL>

绑定变量效率测试
dbms_utility.get_time;
 用于返回百分秒时间 一般都是取差值
 记录程序运行前时间戳 再记录程序运行后时间戳 想减后除以100即可等到秒单位消耗单位
dbms_lock.sleep(1.3); 
 睡眠1.3秒
DECLARE
i NUMBER;
j NUMBER;
BEGIN
  i := dbms_utility.get_time;
  dbms_lock.sleep(1.3);
  j := dbms_utility.get_time;
  dbms_output.put_line((j-i)/100);
END;       
/
创建实验表
create table t1 as select rownum rn,d.* from dba_objects d;
SQL> select count(*) from t1;
  COUNT(*)
----------
     50163

修改软软解析参数
SQL> alter system set session_cached_cursors=0 scope=spfile;
System altered.
Elapsed: 00:00:00.07
SQL> startup force
ORACLE instance started.
Total System Global Area  285212672 bytes
Fixed Size      1267068 bytes
Variable Size     92277380 bytes
Database Buffers   188743680 bytes
Redo Buffers      2924544 bytes
Database mounted.
Database opened.
SQL>
把shared_pool清空
SQL> alter system flush shared_pool;
System altered.
启用SQLPLUS时间记录
SQL> set timing on
未使用绑定变量:
begin
        for i in 1..10000
        loop
           execute immediate 'select object_name from t1 where rn='||i;
        end loop;
end;
/

PL/SQL procedure successfully completed.
Elapsed: 00:00:20.30
SQL>
使用绑定变量:
begin
        for i in 1..10000
        loop
           execute immediate 'select object_name from t1 where rn=:x' using i;
        end loop;
end;
/

PL/SQL procedure successfully completed.
Elapsed: 00:00:00.29
SQL>
天壤之别 显而易见
创建解析树、生成执行计划对于sql的执行来说是开销昂贵的动作
Oracle利用内部的hash算法来取得该sql的hash值,然后在library cache里查找是否存在该hash值
假设“相同”,就将利用已有的解析树与执行计划,而省略了优化器的相关工作。这也就是软解析的过程.
ORACLE在执行的时候只需要编译一次,随后执行9999次都是从共享池中共享的执行计划.
再开软软解析
SQL> alter system set session_cached_cursors=20 scope=spfile;
System altered.
Elapsed: 00:00:00.02
SQL> startup force
ORACLE instance started.
Total System Global Area  285212672 bytes
Fixed Size      1267068 bytes
Variable Size     96471684 bytes
Database Buffers   184549376 bytes
Redo Buffers      2924544 bytes
Database mounted.
Database opened.
使用绑定变量:
begin
        for i in 1..10000
        loop
           execute immediate 'select object_name from t1 where rn=:x' using i;
        end loop;
end;
/
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.29
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.29
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.27
SQL>
和软解析差异不明显.
 
library cache 重要视图
SQL> desc v$librarycache  调优时期会讲解
 Name                           Null?    Type
 ------------------------------ -------- ----------------------------
 NAMESPACE                      VARCHAR2(15)
 GETS                           NUMBER  可以理解为某个object解析的时候查找的次数(解析阶段)
 GETHITS                        NUMBER  get命中次数
 GETHITRATIO                    NUMBER  这个值等于gethits/gets
 PINS                           NUMBER  某个object 解析过后被执行的次数(发生在执行阶段)
 PINHITS                        NUMBER  pin命中次数
 PINHITRATIO                    NUMBER  这个值等于pinhits/pins
 RELOADS                        NUMBER  父游标匹配 但产生新的子游标 或者对象被解析后长时间不用排出内存又重载 都会时此值递增
 INVALIDATIONS                  NUMBER  某个对象无效,通常由于对象定义被更改,需要从新解析
 DLM_LOCK_REQUESTS              NUMBER
 DLM_PIN_REQUESTS               NUMBER
 DLM_PIN_RELEASES               NUMBER
 DLM_INVALIDATION_REQUESTS      NUMBER
 DLM_INVALIDATIONS              NUMBER
共享池命中率
SQL> select sum(pinhits-reloads)/sum(pins)*100 "hit radio" from v$librarycache;
 hit radio
----------
67.1637692
Elapsed: 00:00:00.02
begin
        for i in 1..10000
        loop
           execute immediate 'select object_name from t1 where rn=:x' using i;
        end loop;
  6  end;
  7  /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.27
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.28
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.27
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.27
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.27
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.26
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.27
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.28
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.25
SQL> select sum(pinhits-reloads)/sum(pins)*100 "hit radio" from v$librarycache;
 hit radio
----------
82.0049969
Elapsed: 00:00:00.00
SQL>
软硬解析的比重(自启动以来的值)
SQL> select name,value from v$sysstat where name like '%parse%';
NAME             VALUE
-------------------------------------------------- ---------
parse time cpu       144
parse time elapsed      224
parse count (total)     8683
parse count (hard)      887
parse count (failures)        4
Elapsed: 00:00:00.01
SQL>
SQL> select 887/(8683-4)*100 from dual;
887/(8683-4)*100
----------------
      10.2200714
Elapsed: 00:00:00.00
SQL>  反之就是软解析的比重
SQL> select (8683-4-887)/(8683-4)*100 from dual;
(8683-4-887)/(8683-4)*100
-------------------------
        89.7799286
Elapsed: 00:00:00.00
SQL>
当前的共享池大小:
SQL> select sum(sharable_mem) from v$db_object_cache;
SUM(SHARABLE_MEM)
-----------------
   7666147
Elapsed: 00:00:00.06
SQL>
SQL> select name,value from v$sysstat where name like '%parse%';
NAME             VALUE
-------------------------------------------------- ---------
parse time cpu       168
parse time elapsed      241
parse count (total)     9593
parse count (hard)     1019
parse count (failures)        4
Elapsed: 00:00:00.01
begin
        for i in 1..10000
        loop
           execute immediate 'select object_name from t1 where rn=:x' using i;
        end loop;
end;
/
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.27
SQL> select name,value from v$sysstat where name like '%parse%';
NAME             VALUE
-------------------------------------------------- ---------
parse time cpu       168
parse time elapsed      241
parse count (total)     9599
parse count (hard)     1019
parse count (failures)        4
Elapsed: 00:00:00.00
begin
        for i in 1..10000
        loop
           execute immediate 'select object_name from t1 where rn='||i;
        end loop;
end;
  7  /
PL/SQL procedure successfully completed.
Elapsed: 00:00:04.27
SQL> select name,value from v$sysstat where name like '%parse%';
NAME             VALUE
-------------------------------------------------- ---------
parse time cpu       606
parse time elapsed      589
parse count (total)           19603
parse count (hard)           11020
parse count (failures)        4
Elapsed: 00:00:00.00
SQL>
共享池剩余大小:
SQL> select * from v$sgastat where name='free memory' and pool='shared pool';
POOL      NAME           BYTES
------------ -------------------------------------------------- ----------
shared pool  free memory       34302432
Elapsed: 00:00:00.02
SQL>

设置共享池大小
当10G设置了SGA_target一个大于0的值时,shared_pool大小oracle利用ASMM机制自动管理
即使手动管理我们也只可以设置这个shared_pool_size总体大小,字典缓存和库缓存我们无法干涉各自的大小
共享池中高速缓存的使用效率取决于命中率
命中率高表示不需要从硬盘读数据.命中率低大部分是因为没使用绑定变量
查询执行次数和失效次数
SYS@cecis > select sum(reloads)/sum(pins)*100 from v$librarycache;
SUM(RELOADS)/SUM(PINS)*100
--------------------------
  .041438618
SYS@cecis >
如果此值大于1或更大,就需要加大共享池的大小.
oracle会重复使用相同的数据库对象.如果程序频繁访问硬盘,就说明数据字典高速缓存过快失效(被挤出内存)造成的.
查询用户可以获得gets(找到对象)次数和getmisses(高速缓存失效)的次数:
SYS@cecis > select sum(getmisses)/sum(gets) * 100 from v$rowcache;
SUM(GETMISSES)/SUM(GETS)*100
----------------------------
    .613136846
SYS@cecis >
如果此值大于10%,就需要加大shared_pool_size参数值.

自动管理SGA时 设置共享池的建议
SQL> SELECT SHARED_POOL_SIZE_FOR_ESTIMATE,SHARED_POOL_SIZE_FACTOR FROM  V$SHARED_POOL_ADVICE;
SHARED_POOL_SIZE_FOR_ESTIMATE SHARED_POOL_SIZE_FACTOR
----------------------------- -----------------------
      52   .5909
      64   .7273
      76   .8636
      88       1
     100         1.1364
     112         1.2727
     124         1.4091
     136         1.5455
     148         1.6818
     160         1.8182
     172         1.9545
     184         2.0909
12 rows selected.
SQL>

保留共享池
这个保留共享池的默认大小是共享池的5%。它的大小也可以通过参数SHARED_POOL_RESERVED_SIZE 来调整。
保留区是从共享池中分配,不是直接从SGA 中分配的,它是共享池的保留部分,用于存储超长的SQL
SQL> show parameter shared_pool
NAME         TYPE  VALUE
------------------------------------ ----------- ------------------------------
shared_pool_reserved_size      big integer 4404019
shared_pool_size       big integer 0
SQL>
SQL> select name,value from h$parameter where name like '%shared_pool_re%';
NAME         VALUE
-------------------------------------------------- ------------------------------
_shared_pool_reserved_pct      5
_shared_pool_reserved_min_alloc      4400
Elapsed: 00:00:00.03
SQL>
Shared Pool 中内存大于4400 字节的SQL就会被存放在共享池的保留部分。而这个大
小限制是通过隐含参数_SHARED_POOL_RESERVED_MIN_ALLOC 来设定的(隐含参数不要去修改它)。
除了在实例启动过程中,所有小于这个数的内存段请求永远都不会放到保留部分中,
而大于这个值的大内存段也永远不会存放到非保留区中,即使共享池的空间不够用的情况下也是如此。
保留区的空闲内存也不会被包含在普通共享池的空闲列表中。它会维护一个单独的空闲列表。

通过视图V$SHARED_POOL_RESERVED 可以查到保留池的统计信息。
SQL> select FREE_SPACE,USED_SPACE,MAX_USED_SIZE,REQUESTS,REQUEST_MISSES from V$SHARED_POOL_RESERVED;
FREE_SPACE USED_SPACE MAX_USED_SIZE   REQUESTS REQUEST_MISSES
---------- ---------- ------------- ---------- --------------
   3406208     0    0      0      0
Elapsed: 00:00:00.00
SQL>
其中字段 REQUEST_MISSES 记录了没有立即从空闲列表中得到可用的大内存段请求次数。这个值要为0。
因为保留区必须要有足够个空闲内存来适应那些短期的内存请求,而无需将那些需要长期cache 住的没被pin 住的可重建的段清除。
否则就需要考虑增大SHARED_POOL_RESERVED_SIZE 了。
你可以通过观察视图V$SHARED_POOL_RESERVED 的MAX_USED_SPACE 字段来判断保留池的大小是否合适。
大多数情况下,你会观察到保留池是很少被使用的,也就是说5%的保留池空间可能有些浪费。
但这需要经过长期观察来决定是否需要调整保留池大小。
保留区使用shared pool 的LRU 链表来管理内存块,但是在做扫描时,相互是不受影响的。

keep常见对象到共享池
将重要、常用对象(存储包,触发器,函数,序列等)保持(Keep)在共享池中。
Oracle 解析一个 PL/SQL 程序单元,也需要从共享池中分配内存给这些程序单元对象。
由于这些对象一般比较大(如包),所以分配的内存空间也相对较大。
系统经过长时间运行后,共享池可能存在大量内存碎片,导致无法满足对于大块内存段的分配。
为了使有足够空间缓存大程序块,Oracle 专门从共享池内置出一块区域来来分配内存,保持这些大的对象。
根据LRU 算法,一些一段时间没有使用到的内存块会被释放。
这就可能导致一些重要的对象(如一个含有大量通用算法函数的包、被cache 的序列)
被从内存中清除掉。要在内存中重建他们的代价非常大。
我们可以通过调用存储过程DBMS_SHARED_POOL.KEEP 将这些对象保持在共享池中来降低这种风险。
这个存储过程立即将对象及其从事对象载入library cache 中,并将他们都标记为保持(Keeping)状态。
对于这种对象,我们建议在实例启动时就Keep 住,以减少内存碎片的几率。
加载这个包的代码
SQL> conn / as sysdba
Connected.
SQL> @?/rdbms/admin/dbmspool.sql
Package created.

Grant succeeded.

View created.

Package body created.
SQL>
DBMS_SHARED_POOL.KEEP OR UNKEEP(name ,flag)
当第一次加载时锁定此对象在shared pool 中,永远不释放,除非你主动释放。可以改进性能

name : 对象的名称 如果是SQL则写的是SQL_address和HASH_VALUE
flag : p 包、存储过程、函数;Q 序列 ;R 触发器;T 对象类型;C SQL游标;JS,JC,JR,JD为java相关

keep 一个SQL 写('address,hash_value','C')
SQL> exec dbms_shared_pool.unkeep('2C2EBCE8,2736166827','C');
PL/SQL procedure successfully completed.
SQL> exec dbms_shared_pool.keep('2C2EBCE8,2736166827','C');
PL/SQL procedure successfully completed.
SQL>
 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24756465/viewspace-717611/,如需转载,请注明出处,否则将追究法律责任。

上一篇: 调整SGA大小
下一篇: db buffer cache
请登录后发表评论 登录
全部评论

注册时间:2012-03-03

  • 博文量
    42
  • 访问量
    37666