Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1179485
  • 博文数量: 398
  • 博客积分: 10110
  • 博客等级: 上将
  • 技术积分: 4055
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-23 20:01
个人简介

新博客http://www.cnblogs.com/zhjh256 欢迎访问

文章分类

全部博文(398)

文章存档

2012年(1)

2011年(41)

2010年(16)

2009年(98)

2008年(142)

2007年(100)

我的朋友

分类: Oracle

2008-01-06 21:26:22

PLSQL程序调优系列八(编译PL/SQL代码本地执行)

       可以通过编译PL/SQL过程到本地码驻留在共享库内提高性能,这些过程将会被编译成C代码,然后使用C编译器变异并链接到Oracle进程。

       可以使用本地编译编译Oracle内置过程或者用户自定义过程。这种方式可以在MTSRAC下工作。

准备工作

       必须首先在测试环境下试验,然后考虑是否在生产系统下使用。

       通常在配置数据库为本地编译前备份数据库,如果发现编译花费的时间超过了得到的性能好处,可以转储备份的数据库,因为重新编议回推断器模式花费的时间会更长。

       某些步骤需要DBA权限,必须在服务器上改变某些初始化参数,创建一个目录,并且这个目录在服务器实例的数据文件附近。服务器同时需要C编译器,在RAC下,每个节点都需要一个编译器。具体的预要求在Oracle的安装文档中有详细的解释。

决定是否使用PL/SQL的本地编译

       对于计算为主的应用程序,PL/SQL本地编译提供了最好的性能,特别是数据仓库应用程序和在服务器端转换显示的数据的应用程序。

       由于该技术不能提高SQL的速度,因此特别适合于那些主要时间不是花费在SQL处理上的应用程序。可以通过比较本地编译和推断器编译查看性能。

       编译程序单元花费的时间将比默认的编辑更长的时间,因此在开发过程中,对于经常需要重新编译的程序应该关闭本地编译。

PL/SQL本地编译的工作机制

       如果不使用本地编译,PL/SQL程序单元将编译为中间码,机器可读的形式。机器码存储在DD中并在运行时被推断。使用PL/SQL本地编译,PL/SQL语句将转换为C代码以绕过运行时推断,得到更好的运行时性能。

       PLSQL_初始化参数设置PL/SQL本地编译的环境,PL/SQL使用$ORACLE_HOME/plsql/spnc_commands命令文件,和操作系统支持的C编译器以及链接器编译和链接C代码到共享库。

       共享库存储在DD中,因此它们被自动备份以防止被删除。这些共享库文件被拷贝到文件系统并在PL/SQL子程序被调用时加载和运行。如果文件在数据库关闭时被删除,或者改变了保存库的目录,它们将会被自动提取。

       虽然仅仅调用SQLPL/SQL可能没有提高性能或者很少,但是本地编译的PL/SQL至少等于相应的推断模式的性能,即大于等于。编译的代码与相应的推断模式的库调用相同,即行为完全相同。

依赖性,失效和重新生效

       在过程被编译并转化到共享库后,它们将自动被链接到Oracle进程。不需要重启数据库或者移动共享库到其他位置。可以在存储过程之间来回调用,不管它们全部是默认模式还是本地编译模式,或者混合模式。

       重新编译在无效的PL/SQL模块上自动进行。例如,如果一个本地编译的PL/SQL模块以来的对象被改变了,子程序将会失效。当下一次相同的子程序被重新调用时,数据库将自动重编译子程序。由于PLSQL_CODE_TYPE设置存储在每个子程序的库单元内,自动重编译将使用这个存储设置的代码类型。

       只有当重新编译是重新生效的一部分时,存储设置才会有用。如果PL/SQL子程序显示通过CREATE OR REPLACE or ALTER...COMPILE编译,将使用当前的会话设置。产生的共享库存储在SYSTEM表空间中,当本地编译的过程第一次执行时,相应的库文件将被从数据库拷贝到PLSQL_NATIVE_LIBRARY_DIR声明的目录。

RAC和本地编译

       每个节点都需要C编译器并且进行恰当的配置,以及到$ORACLE_HOME/plsql/spnc_commands的路径。

       RAC中使用PLSQL本地编译时,共享库文件的原始拷贝存储在数据库中,并且他们会被自动传播到所有节点,不需要额外的工作。

       确保所有的RAC节点使用相同的配置,并且确保各个节点的PLSQL_NATIVE_LIBRARY_DIR设置都相同。

本地编译的限制

       ·PL/SQLDEBUG工具不能处理编译为本地执行的过程;

       ·当大量的过程/包被编译为本地执行时,将所有共享对象存储在一个目录中将会影响系统性能。

spnc_commands文件

       spnc_commands文件在$ORACLE_HOME/plsql目录下,包含了编译和链接到每个程序的命令模板。spnc_commands命令中包含了默认C编译器的位置,只有一个编译器可以用来编译PL/SQL模块,不要使用不同的编译器编译PL/SQL模块。

       可以查看spnc_commands确认命令模板的正确性。不应该改变该文件除非SA改变了C的安装路径。

PL/SQL本地编译的初始化参数设置

       查看当前设置可以使用:SHOW PARAMETERS PLSQL

       PLSQL_NATIVE_LIBRARY_DIR初始化参数

       这是系统级别唯一要求的参数设置,声明包含编译的PL/SQL代码的共享库的全路径和目录名,该值必须被显示设置并指向已存在,可访问的目录;该目录不能包含变量如ORACLE_HOME

       如:PLSQL_NATIVE_LIBRARY_DIR='/oracle/oradata/db1/natlib'

       或:ALTER SYSTEM SET PLSQL_NATIVE_LIBRARY_DIR='/oracle/oradata/db1/natlib'

       根据OFAOracle推荐将该目录设置为数据文件所在目录的子目录;

       PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT初始化参数

       该参数声明PLSQL_NATIVE_LIBRARY_DIR目录中可以创建的子目录的数量。

       如:PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT=1000;

       PLSQL_CODE_TYPE初始化参数

       PLSQL_CODE_TYPE声明PL/SQL被编译为本地或者推断器模式;该参数可以是系统级别,会话级别,以及具体的PL/SQL模块。如果编译整个数据库为NATIVEOracle推荐将PLSQL_CODE_TYPE在系统级别设置。

ALTER SESSION SET PLSQL_CODE_TYPE='NATIVE';
ALTER SESSION SET PLSQL_CODE_TYPE='INTERPRETED';

ALTER PROCEDURE hello_native COMPILE PLSQL_CODE_TYPE=NATIVE REUSE

SETTINGS;

       需要注意,包声明和包体不需要编译为相同的模式。

设置PL/SQL库本地子目录

       默认情况下,PL/SQL存储在一个子目录。但是如果文件很多,OS可能比较难以在一个目录中处理。Oracle推荐将文件放在多个子目录下。

       如果要迁移一个数据库到新的位置,或者要设置一个测试数据库,需要使用以下查询确定使用的PL/SQL程序单元数。

       如果要设置本地库子目录,首先创建顺序的子目录,可以使用以下脚本:

SPOOL make_dirs
BEGIN
  FOR j IN 0..1000 -- change to the number of directories needed
  LOOP
    DBMS_OUTPUT.PUT_LINE ( 'mkdir d' || TO_CHAR(j) );
  END LOOP;
END;
/
SPOOL OFF

       然后设置PLSQL_NATIVE_LIBARY_SUBDIR_COUNT参数:

       ALTER SYSTEM SET PLSQL_NATIVE_LIBRARY_SUBDIR_COUNT=1000;

 

设置和测试PL/SQL本地编译

       设置和测试一个/多个子程序使用本地编译的过程如下:

·设置必要的参数;

·编译一个/多个子程序;

CREATE OR REPLACE创建和重编译子程序;

ALTER PROCEDURE, ALTER FUNCTION, or ALTER PACKAGECOMPILE PLSQL_CODE_TYPE=NATIVE REUSE SETTINGS;

使用预定义初始化参数PLSQL_CODE_TYPE=NATIVE创建一个数据库;

如下:

-- PLSQL_NATIVE_LIBRARY_DIR must be set to an existing, accessible directory

SET SERVEROUTPUT ON FORMAT WRAPPED

 

CREATE OR REPLACE PROCEDURE hello_native AS

BEGIN

  DBMS_OUTPUT.PUT_LINE('Hello world. Today is ' || TO_CHAR(SYSDATE) || '.');

END hello_native;

/

 

ALTER PROCEDURE hello_native COMPILE PLSQL_CODE_TYPE=NATIVE REUSE SETTINGS;

SHOW ERRORS

-- check for a file HELLO_NATIVE... in the PLSQL_NATIVE_LIBRARY_DIR directory

CALL hello_native();

·为了确保能够正确工作,可以查询DD确定过程被编译为本地执行。ALL_PLSQL_OBJECT_SETTINGS视图的PLSQL_CODE_TYPE列为NATIVE

设置一个新的数据库为PL/SQL本地编译

·确保spnc_commands有正确的命令模板;

·确保PL/SQL本地库目录在每个数据库已创建;

  必须在每个数据库上设置了PL/SQL库;

  创建一个目录;

·设置必要的参数;

  如果使用DBCA,确保PLSQL_NATIVE_LIBRARY_DIR指向可访问的目录并且PLSQL_CODE_TYPENATIVE

更改数据库的配置

1.  确保配置了以下条件:
确保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;

阅读(2267) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~