SGA 中的另外一个重要结构是共享池。共享池存储了应用执行需要的PL/SQL块结构,SQL语句的文本、SQL编译后的可
执行代码、系统数据字典等。
恰当的共享池尺寸设置将减少系统各种资源的使用。首先,对于SQL、PL/SQL 来说,共享池提供了运行状态下的临时
存储点,后续执行的SQL和PL/SQL将使用已被缓存的编译结果及执行计划,有效减少系统CPU的使用,减少用户调用事件。
第二,栓、锁资源的争用被环节。第三,数据字典信息将被缓存在共享池中,因此,有关系统的信息不必再去执行查询,
这就降低了资源的使用。
在库缓存中区域中,存储着SQL、PL/SQL、Java类的源码、执行计划、伪编译后可执行代码等。当应用程序运行时,这些代码会被调用。如果这些代码在前面不久的应用运行中已经被调用执行过,则可能被后续执行的应用程序共享。默认地,Oracle将试图重复使用现有的代码,实现重用。也就是说,后续应用的执行能够引用前期应用执行中编译过的代码,这称为库缓存的“命中”。一次命中意味着一次
如软解析,SQL、PL/SQL的硬解析及编译过程的资源开销将被避免。
假设后续应用在执行中不能通过库缓存实现“软解析”,Oracle 不得不为SQL、PL/SQL 进行语法解析、执行计划分析和编译,以及
应用代码可执行版本的创建。这个过程称为“硬解析”,硬解析需要整个系统付出额外的CPU时间片、库缓存栓资源等。
从性能上看,我们当然希望能尽可能地实现软解析,减少硬解析。做到这一点需要进行两方面的准备工作:能够重用的SQL和
PL/SQL、足够尺寸的共享池。
SQL与PL/SQL重用
当用户想Oracle 发出SQL、PL/SQL请求时,Oracle将首先确定这些SQL语句、PL/SQL块是否可以在共享池中找到相同的
语句,过程如下:
1>根据要执行的语句文本,和共享池中现有语句文本进行比较
2>如果共享池中没有找到相同的语句,说明SQL语句在共享池中不存在,开始执行硬解析操作。
3>如果找到匹配的语句,Oracle 继续把匹配语句的正文和缓存池中的SQL正文进行严格比较,包括空格、大小写、注释等。
例如下面两条语句就是不同的,虽然只是多了一个空格、大小写有些不一致。
SELECT name FROM Mytable;
SELECT name FROM mytable;
Oracle在比较语句时,除了比较SQL、PL/SQL文本,也会比较其引用对象。假设两条语句的文本完全一致,但对象属主是另外
的模式,则Oracle也认为该语句是不同的。
1>实现游标共享
在可能的情况下使用绑定变量来替换SQL中的常量。例如,下面两个SQL语句来自不同的两个用户:
SELECT name FROM mytable WHERE id= 1;
SELECT name FROM mytable WHERE id= 2;
从Oracle的角度看,这两个SQL语句是不同的,因为文本不同。下面的语句解决了这个问题
SELECT name FROM mytable WHERE :v_id= 1;
在上面的语句中,变量v_id 替换了文本,在运行时进行变量赋值即可。要做到这一点,开发中必须遵守如下的共识:首先项目中的
程序员应采用相同的编程规范,其次程序中尽量避免使用动态SQL。最后,尽量使用存储过程、函数或者包、包体。
2>避免执行DDL语句
避免在系统高峰时段执行表的DDL操作,因为这会导致依赖于表、索引的SQL必须做硬解析---他们所依赖的对象结构发生了改变。
3>将序列驻留在缓存中
对于系统中经常使用的序列对象,DBA 最好给他赋予足够的缓存,这会减少数据字典栓(资源锁)的使用频率。因此在CREATE
SEQUENCE 或 ALTER SEQUENCE 中加上Cache 关键词,可以使序列对象长驻缓存。示例如下:
SQL>CREATE SEQUENCE SCOTT.MY_SEQ1 CYCLE ORDER CACHE 20 MAXVALUE 20000 MINVALUE 1 INCREMENT BY 1 START WITH 1;