ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 高性能PL/SQL编程经验谈四(系统设置篇)

高性能PL/SQL编程经验谈四(系统设置篇)

原创 Linux操作系统 作者:木呼 时间:2011-06-14 14:06:50 0 删除 编辑

系统设定篇

避免动态重编译

什么是pl/sql的动态重编译

在某个Pl/sql程序中(假定为AP1)用到的对象被删除,修改或者重新生成了,那么AP1的状态就变成了INVALID,比如ap1过程调用到了ap2这个过程,ap2在一次编译中报错了,改完ap2并编译完后,ap1也就变成了invalid状态,

oracle8开始,ap1执行的时候,会对他进行重新编译,只要没有编译错误ap1就可以继续执行

ap1的重编译会占用一定的时间,所以应该尽量避免这种情况发生。为了避免这种情况,我们应当最大限度的去了解对象间的关联。以及别在过程中创建需要使用的对象等。

下面说说查看对象关联的方法。

第一种方法,使用utldtree

我们需要执行下面三步才能看到

第二种 直接看数据字典 user_dependencies

列名

列说明

NAME

对象名称

TYPE

NAME列的对系那个类型

REFERENCED_OWNER

NAME列的对象有关联的对象的所有者名字

REFERENCED_NAME

NAME列的对象有关联的对象的名称

REFERENCED_TYPE

NAME列的对象有关联的对象的类型

REFERENCED_LINK_NAME

如果是远程对象,所使用的dblink的名字

 

 

让执行部分常驻内存

存储过程常驻内存,这个方法是把双刃剑,虽然能使用存储过程的调用速度加快,特别是在某个过程使用频率很高的情况下,但是如果过分的使用,则会增加共享池的负荷。所以pl/sql的优化主要还是集中在编程以及sql优化中,当某个过程调用频率到达一定程度才使用。当然如果某些执行的过程频繁使用了某些table对象,我们也可以把table常驻内存,以提高过程中sql的执行效率。

下面说说让执行部分常驻内存的方法,如何使用DBMS_SHARED_POOL将对象常驻内存。

写了大半,网上有哥们写的比俺还详细,以下这段copy吧。

1DBMS_SHARED_POOL作用
 DBMS_SHARED_POOL
包的作用把需要的对象pinshared pool中,由此被pin住的对象就
 
不再受shared pool LRU法则的约束而永久的驻留在shared pool中。
2
DBMS_SHARED_POOLshared_pool_reserved区别
 shared_pool_reserverd
的含义是,当shared_pool 被不断的写入,同时由于LRU法则的存在
 
较旧的对象被交换出去,这样就会造成shared_pool被分割成许多较小的区域,这时如果应用
 
请求一个 较大的连续的内存区域时,如果没有shared_pool_reserved的存在,oracle就会
 
去搜索整个shared pool以寻找一个连续的较大区域,当搜索不到满足需求的区域时,oracle
 
就不得不释放一些区域来满足新来的需求,这样就可能造成性能的下降,因为被释放的区域可能
 
恰恰是其他应用所需要的,oracle又不得不进行重新解析。为了避免这种情况的出现,
 shared_pool_reserverd_size
用来设置一个shared pool 保留的区域,用于应用对较大内存
 
区域的需求,保留区的信息可以查询v$shared_pool_reserved视图。
3
、创建DBMS_SHARED_POOL
 DBMS_SHARED_POOL
可以由?\RDBMS\ADMIN\DBMSPOOL.SQL创建

SQL> @?\rdbms\admin\dbmspool.sql

程序包已创建。


授权成功。


视图已创建。


程序包体已创建
 
查询v$db_object_cache视图,看dbms_job包在library cache中的状态。
 v$db_object_cache
用于查询cachelibrary cache中的对象信息,这里的对象包括表,
 
索引,聚簇,同义词,PL/SQL过程,包,触发器。
SQL> col name for a20
SQL> col type for a20
SQL> select name,type,sharable_mem,loads,kept from v$db_object_cache
  2   where upper(name)=upper('dbms_job');

NAME                 TYPE                 SHARABLE_MEM      LOADS KEP
-------------------- -------------------- ------------ ---------- ---
DBMS_JOB             NOT LOADED                      0          1 NO
DBMS_JOB             NOT LOADED                      0          1 NO

 dbms_job包进行keep操作
SQL> exec dbms_shared_pool.keep('dbms_job');

PL/SQL 过程已成功完成。
SQL> select name,type,sharable_mem,loads,kept from v$db_object_cache
  2   where upper(name)=upper('dbms_job');

NAME                 TYPE                 SHARABLE_MEM      LOADS KEP
-------------------- -------------------- ------------ ---------- ---
DBMS_JOB             PACKAGE                     20828          2 YES
DBMS_JOB             PACKAGE BODY                12636          2 YES

 dbms_job包进行unkeep操作
SQL> exec dbms_shared_pool.unkeep('dbms_job');

PL/SQL 过程已成功完成。

SQL> select name,type,sharable_mem,loads,kept from v$db_object_cache
  2   where upper(name)=upper('dbms_job');

NAME                 TYPE                 SHARABLE_MEM      LOADS KEP
-------------------- -------------------- ------------ ---------- ---
DBMS_JOB             PACKAGE                     20828          2 NO
DBMS_JOB             PACKAGE BODY                12636          2 NO

 FLUSH shared pool
SQL> alter system flush shared_pool;

系统已更改。

SQL> select name,type,sharable_mem,loads,kept from v$db_object_cache
  2   where upper(name)=upper('dbms_job');

NAME                 TYPE                 SHARABLE_MEM      LOADS KEP
-------------------- -------------------- ------------ ---------- ---
DBMS_JOB             NOT LOADED                      0          2 NO
DBMS_JOB             NOT LOADED                      0          2 NO

NATIVE编译

偶在工作中也很少使用到,其实很多时候还是数据类型以及书写方法更重要,不过native编译还是有点用处的,不过oracle10g之后效果就不明显了,而在oracle11g中已经自动的给存储过程native编译了。

Native编译通过将 PL/SQL 模块(程序包、触发器、过程、函数和类型)编译成驻留在共享库中的纯代码来加速它们的运行。过程被转换成 C 代码,然后用一个 C 编译器进行编译,并与 Oracle 进程动态链接。

如果未使用native编译,则将每个 PL/SQL 程序单元编译成一种中间形式的机器可读码 (MCode)MCode 存储在数据库字典中,并在运行时进行解释。

使用 PL/SQL native编译,将 PL/SQL 程序编译成无需运行时解释的纯机器码,从而加快运行速度。

Oracle10g native 设定方法

确保配置了以下条件:

1.确保spnc_commands$oracle_home/plsql/spnc_commands具有正确的命令模板并且安装了恰当的C编译器;
设置了PLSQL_NATIVE_LIBRARY_DIR参数(创建存放编译记过的目录的绝对路径);
设置了PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT
可以编译单个PL/SQL单元;

2  关闭应用程序服务,监听,数据库;
关闭所有应用程序服务,包括FORMSWEB服务器等;
关闭TNS监听;
正常或者IMMEDIATE关闭数据库;

3  在数据库初始化参数文件中设置PLSQL_CODE_TYPETRUE

4  使用UPGRADE选项启动数据库;

5  执行以下过程列出所有INVALIDPL/SQL单元。

SELECT o.OWNER, o.OBJECT_NAME, o.OBJECT_TYPE
  FROM DBA_OBJECTS o, DBA_PLSQL_OBJECT_SETTINGS s
 WHERE o.OBJECT_NAME = s.NAME
   AND o.STATUS = 'INVALID';

如果任何内置的对象无效,尝试使它们重新生效:

ALTER PACKAGE OLAPSYS.DBMS_AWM COMPILE BODY REUSE SETTINGS;

            6.执行以下查询确定NATIVEINTERPRETED的对象的数量

SELECT TYPE, PLSQL_CODE_TYPE, COUNT(*)

  FROM DBA_PLSQL_OBJECT_SETTINGS

 WHERE PLSQL_CODE_TYPE IS NOT NULL

 GROUP BY TYPE, PLSQL_CODE_TYPE

 ORDER BY TYPE, PLSQL_CODE_TYPE;

plsql_code_typeNULL的对象可以忽略。

7.以SYS运行$ORACLE_HOME/rdbms/admin/dbmsupgnv.sql更新DD中所有PL/SQL单元的plsql_code_typeNATIVE,然后使用TRUE排除包声明。该过程必须在数据库在UPGRADE模式时完成。

8.关闭并且NORMAL启动数据库,执行ALTER SYSTEM ENABLE RESTRICTED SESSION

9.运行$ORACLE_HOME/rdbms/admin/utlrp.sql命令,该脚本重编译所有PL/SQL模块,如果非正常终止,则重新运行。

            10.在编译完全成功后,确保没有新的无效PL/SQL,使用第五步的脚本;

11.运行第6步,确保除TYPE 和包声明外,全部PL/SQL单元为NATIVE,如果运行了dbmsupgin.sql,则全部为INTERPRETED

12.执行ALTER SYSTEM DISABLE RESTRICTED SESSION;

 

 

Oracle11g native的设定方法

11g就简单多了 Oracle弄了个pl/sql编译器比c编译器还牛掰。

改两参数

alter system set plsql_code_type=native;

alter system set plsql_optimize_level=3;

PLSQL_OPTIMIZE_LEVEL  这个参数还是介绍下,oracle一般都建议我们不要修改

10g中还没3这个值

等于0呢,没什么实际意义

1表示不做任何特殊处理

2可能会修改你的源码,做一些优化

设置为3时,PL/SQL 编译器重写代码以内联该代码。

 

针对单个的plsql程序

alter procedure 'XXX' compile plsql_code_type=native;

alter procedure 'XXX' compile plsql_optimize_level=3;

可以通过all_plsql_object_settings视图来查看plsql代码的编译方式

官方文档上说比C编译器快1-2倍,用了循环乘法测试,速度比解释方式快10倍,当然普通的程序不可能快这么多,反正总是好功能。

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

请登录后发表评论 登录
全部评论

注册时间:2010-04-19

  • 博文量
    93
  • 访问量
    154190