7、批次生成FMX文件
用RUN命令,一次只能生成一个FMX文件,如果想生成一 批FMX文件,这样做即麻烦又费时,一个生成FMX较快的办法是:先打开要运行的FMB文件,然后按住SHIFT键将这些文件全部选中后,再鼠标单击系统 主菜单中"文件"菜单项的子菜单项"ADMINISTRATION"中"GENERATE"按钮即可
8、屏蔽英文提示信息的两种方法
在应用程序中,系统提示信息为用户提供参考信息,帮助用户正确使用系统。但运行Oracle form时,屏幕下方信息行的提示信息却是英文。当有两个以上信息等待在信息行上显示时,这些英文信息还会以窗口方式出现在屏幕中央。如何避免这种情况?
Oracle form将每个信息定义了重要级别,用于表明该信息是重要还是不重要。共有如下六个等级:
重要级别                   意 义
        0                     所有信息
5                       重申明显的条件
10                   操作人员产生了一个过程错误
15                   操作人员试图执行form未设计的动作
20                   由于触发子问题或某些其他突出问题不能继续动作
25                   可能引起form不正确完成任务的一个条件
>25                   开发人员不能压缩的信息
开发人员可压缩的最大信息级别为25,使用如下语句禁止系统信息显示
:system.massege-level:=′25′;     ----禁止显示信息级别不大于25的系统信息
:system.suppress-working:=′TRUE′; ----禁止显示系统处理一个动作时的工作信息
注意:这种方法只能屏蔽信息级别小于等于25的系统信息。
此外,使用message语句的no_acknowledge参数,可避免使用复杂的message_level。
message('msg',no_acknowledge);
9、截获系统信息,转换为汉字提示信息
Oracle form中有两个触发子on-erro和on-message,分别在显示系统错误信息和通知信息(告诉操作人员当前处理状态或给出上下文相关的信息)时 触发,在触发子中插入pl/sql代码实现汉字提示信息替换英文提示信息。例如:在on-erro触发子中插入以下编码:
Begin
If erro-code=40202 and error-type=′FRM′
Then message(′字段值必须键入!′);
bell;
End if;
End;
这样,当有"form--40202"号错误时,系统信息行的提示信息会由原来的英文"field must be enterd"变为汉字"字段值必须键入!",用户不用再为不认识的提示犯愁了。
10、 用FORMS实现ORACLE数据库与其它数据源数据的交换
Developer/2000 不能实现同时多数据源的同时连接, 在多系统和异种数据源的操作中功能确实大打折扣, 虽然可以用3GL加ODBC作一DLL应用能实现,但一般的应用中又有点没用必要作的那么复杂。实际上Developer/2000内嵌包TEXT_IO 为我们提供了一个更简单的方法。 几乎所有的数据库或数据库前端开发工 具都提供文本文件的操作, 这样我们完全可以用文本文件作为数据交换的通用格式。下例是在保险业中的一应 用:( 要 用 到d2kwfile.dll 应 用)
DECLARE
  filename varchar2(128):=null;
  filenum text_io.file_type;
  linebuf varchar2(100);
  r_temp temp%rowtype;
BEGIN
  filename:=d2k_file_dialog.show('请选择缴费工资台帐原文件','c:/','源文件(*.txt)|*.txt|');
  if filename is null then
  raise form_trigger_failure; end if;
  filenum:=text_io.fopen(filename,'r');
  loop
  BEGIN
    text_io.get_line(filenum,linebuf);
    TEXT_IO.PUT(linebuf);TEXT_IO.NEW_LINE;
    exception when no_data_found then
    exit;
  END;
  BEGIN
    v_temp.l1=substr(linebuf,1,9);
    v_temp.l2:= to_number(substr(linebuf,10,5));
    insert into temp(l1,l2) values (v_temp.l1,v_temp.l2);
    exception when others then
  END;
  end loop;
END;
11、当使用主从块时,如何使从块自动提交 ?
在 FORM设计时有时需要用到主从块,在主从块录入时每当鼠标从从块移到主块准备录入一条新记录时,总是弹出一报警器,问你是否保存数据,从而影响录入速 度,将该报警器去掉的方法是:在过程”CLEAR_ALL_MASTER_DETAILS" 中的"CLEAR_BLOCK(ASK_COMMIT)"即清除从块时是否提交改为”CLEAR_BLOCK(DO_COMMIT)",这样从块录完数据 再导航到主块录入新记录时,系统将自动提交数据,而不再出现上述提示。
12、如何减少FORM所占磁盘空间 ?
(1) 对于块中只用于查询并且无格式限制的项,设置为显示项。
(2) 保存FORM时先断开与数据库的链接,然后在保存。
以上两种方法均可减小FORM的大小,尤其是第二种方法更为明显。当硬盘空间较小,或将程序备份到软盘上时,这样作是很有意义的。
13、ORACLE *Forms 中List Item 动态加载数据的方法
A、打开Form Builder               B、文件(F)→新建(N)→表格(F)
C、新建一个非数据块,取名为tool       D、鼠标右键→布局编辑器(E)
E、建一个列表项,名为xl(属于tool块)   F、新建一过程,内写如下的代码
PROCEDURE create_xl IS           --动态显示学历过程
CURSOR A IS SELECT DISTINCT(xl) FROM t_xl; --建立a游标,从学历表取数据(有可能动态变化)
CNT   NUMBER;              --记录总数变量,用于生成列表的总项数
i     NUMBER;              --循环变量
TNAME t_xl.name%TYPE;          --TNAME变量和t_xl表中name项具有相同的结构
BEGIN
CLEAR_LIST('tool.xl');          --清空列表tool.xl(tool块上的xl项)
SELECT COUNT(DISTINCT(name)) INTO CNT FROM t_xl;   --计算列表总数
OPEN A;                       --打开游标
FOR i IN 1..CNT LOOP                --开始循环
FETCH A INTO TNAME;              --取数
EXIT WHEN A%NOTFOUND;             --退出条件
ADD_LIST_ELEMENT('tool.xl',i,TNAME,TNAME);   --把查询出的值加入列表中   
END LOOP;                      --结束循环
CLOSE A;                      --关闭游标
END;
14、取随机数 between 0 and 1
function f_rand return number is
    a number := 25214903917;   /* Fixed values used in generation */
    c number := 11;
    m number := power(2,48);
begin
    select to_char(sysdate,'sssssdddhhsssss') from dual;
    v_rand := ((a * v_lastval + c ) mod m );
    v_rand := v_rand / m;
end;
15、在form中执行ddl语句
forms_ddl('create table my_table (ship_id number)');
16、在form中使用同步
synchronize;   ---- 可避免某些语句如MESSAGE语句未执行
17、dp中调用dp自带的程序库执行外部命令,如:
  win_api_shell.winexec(v_run,0);
  win_api_utility.delete_file(v_filename);
  注:自带的程序库是PL/SQL Library。必须将相应的PLL文件拷贝至当前目录下,类似于调用DLL
18、用类似于其他语言中的struct结构来存储相关的数据信息,可提高程序的可读性和效率。
  type test_record is record of
              ( a number,
                b number);
  v_r1   test_record;
  v_r1.a:=1;
  v_r1.b:=2;

五、DEVELOP2000/REPORT的使用
1、Oracle Report 3.0汉字输入问题的解决
在 用Oracle Developer/2000安装时,语言请选择English(用户的机器选择Simplified Chinese),然后再用Regedit进行注册表编辑,选取"我的电脑"中的"HKEY-LOCAL-MACHINE"下 的"Software→Oracle",选取Oracle下的NLS-LANG,其缺省值为:AMERICAN- AMERICA.WE8ISO8859P1,修改Server端NLS- LANG的值,可选SIMPLIFIED CHINESE-CHINA.ZHS16CGB231280或AMERICAN-AMERICA.ZHS16CGB231280;
在开发过程中,尽量在第一次将所有汉字输入完毕,待以后再进行调整 ;
当在Report 3.0输入汉字产生非法错误时, 可用NOTEPAD输入汉字后保存在文件中, 然后在Report 3.0 选单"File→Import→Text…",选择该文件,即可将该文件中的汉字输入。
2、使用中间表来控制报表的输出格式
  在打印报表时,我们会遇到这种情况:一个报表中有两个完全不相关联的报表,这两个报表需要并列打印,但两个报表的数据量不同会导致报表的最下面对不齐,这时我们可以使用中间表。
  建两个中间表,这两个中间表的结构除分别和两个报表相同外(不含约束),还要再增加一列,为行计数列,在报表的POST_FORM触发子中将两个报表的数 据和ROWNUM插入到中间表中,根据ROWNUM判断两个报表记录的多少,向少的中间表中插入ROWNUM列,直至两个中间表的记录数相同,再根据两个 中间表生成报表即可。
  同时,对于复杂的报表,往往有多个查询,这时候可以写package,将复杂的数据按格式排好,写到如h_reptmp的临时表中,报表程序只需要写非常简单的select语句就可以,报表运行的速度可以提高许多。
3、报表输出到文本文件
调用报表输出到文本文件时,文本文件的宽度是固定的,不能调整,因此不能有过多的字段,以免不能显示某些字段。
4、Oracle Report Wizard技巧
在Report Wizard中,NCA Yellow模板出现"Print Dialog"窗口,而NCA Gray和 Gray Grid模板中没有出现该窗口。这是由于Report的系统参数 Printjob的缘故,Printjob值判断在打印过程中是否出现打印窗口。我们可在"Data Model→System Parameter→Print job "中将Initial Value的值由"NO"改为"YES"。 在打印横向报表时,我们可先选择打印机为"横打"方式,然后设置系统参数Printjob值为"NO"。
5、如何使不同布局的报表显示在同一页上?
复 杂的报表往往是由几部分组成,需建立多个查询,而每个查询都对应着一个布局,怎样才能使具有不同布局的报表数据显示在同一页上呢?其方法如下:第一步,首 先根据实际报表格式建立第一个查询组的布局,称为布局1,然后依次再建立起其他查询组的布局,分别称为布局2,布局3... ...。注意:每个布局最外围的单选框不要去掉。第二步,分别为布局2,布局3... ... 建立一个到布局1的定位(ANCHOR),即选中工具栏中的ANCHOR,鼠标单击布局2 的单选框, 然后按住鼠标左键并拖动鼠标到布局1的单选框上 (可 以选择上边﹑下边﹑左边或右边), 松开鼠标按钮,按此方法再建立布局3,布局4... ... 到布局1的定位。建立定位的作用是使布局2,布局3... ... 相对与布局1的位置保持不变,这样就使具有不同布局的报表数据显示并打印在同一物理页上。


附摘文章
文章一 为什么有时ORACLE数据库不用索引来查找数据?
当 你运用SQL语言,向数据库发布一条查询语句时,ORACLE将伴随产生一个"执行计划",也就是该语句将通过何种数据搜索方案执行,是通过全表扫描、还 是通过索引搜寻等其它方式。搜索方案的选用与ORACLE的优化器息息相关。一条SQL语句的处理过程要经过以下几个步骤:
1 语法分析 分析语句的语法是否符合规范,衡量语句中各表达式的意义。
2 语义分析 检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限。
3 视图转换 将涉及视图的查询语句转换为相应的对基表查询语句。
4 表达式转换 将复杂的SQL表达式转换为较简单的等效连接表达式。
5 选择优化器 不同的优化器一般产生不同的"执行计划"
6 选择连接方式 ORACLE有三种连接方式,对多表连接ORACLE可选择适当的连接方式。
7 选择连接顺序 对多表连接ORACLE选择哪一对表先连接,选择这两表中哪个表做为源数据表。
8 选择数据的搜索路径 根据以上条件选择合适的搜索路径,如是全表搜索还是用索引或其他的方式。
9 运行"执行计划"
ORACLE 的优化器 ORACLE有两种优化器:基于规则的优化器(RBO, Rule Based Optimizer),和基于代价的优化器(CBO, Cost Based Optimizer)。RBO自ORACLE 6版以来被采用,有着一套严格的使用规则,只要你按照它去写SQL语句,无论数据表中的内容怎样,也不会影响到你的"执行计划",也就是说对数据不"敏 感",ORACLE公司已经不再发展这种技术了。CBO自ORACLE 7版被引入,ORACLE自7版以来采用的许多新技术都是基于CBO的,如星型连接排列查询,哈希连接查询,和并行查询等。CBO计算各种可能"执行计 划"的"代价",即cost,从中选用cost最低的方案,作为实际运行方案。各"执行计划"的cost的计算根据,依赖于数据表中数据的统计分 布,ORACLE数据库本身对该统计分布并不清楚,须要分析表和相关的索引,才能搜集到CBO所需的数据。
一般而言,CBO所选择的"执行计划"都不会比RBO的"执行计划"差,而且相对而言,CBO对程序员的要求没有RBO那么苛刻,节省了程序员为了从多个可能的"执行计划"中选择一个最优的方案而花费的调试时间,但在某些场合下也会存在问题。
较典型的问题有:有时,表明明建有索引,但查询过程显然没有用到相关的索引,导致查询过程耗时漫长,占用资源巨大,问题到底出在哪儿呢?按照以下顺序查找,基本上能发现原因所在。查找原因的步骤:
首 先,我们要确定数据库运行在何种优化模式下,相应的参数是:optimizer_mode。可在svrmgrl中运行"show parameter optimizer_mode"来查看。ORACLE V7以来缺省的设置应是"choose",即如果对已分析的表查询的话选择CBO,否则选择RBO。如果该参数设为"rule",则不论表是否分析过,一 概选用RBO,除非在语句中用hint强制。
其次,检查被索引的列或组合索引的首列是否出现在PL/SQL语句的WHERE子句中,这是"执行计划"能用到相关索引的必要条件。
第 三,看采用了哪种类型的连接方式。ORACLE的共有Sort Merge Join(SMJ)、Hash Join(HJ)和Nested Loop Join(NL)。在两张表连接,且内表的目标列上建有索引时,只有Nested Loop才能有效地利用到该索引。SMJ即使相关列上建有索引,最多只能因索引的存在,避免数据排序过程。HJ由于须做HASH运算,索引的存在对数据查 询速度几乎没有影响。
第四,看连接顺序是否允许使用相关索引。假设表emp的deptno列上有索引,表dept的列deptno上无索 引,WHERE语句有emp.deptno=dept.deptno条件。在做NL连接时,emp做为外表,先被访问,由于连接机制原因,外表的数据访问 方式是全表扫描,emp.deptno上的索引显然是用不上,最多在其上做索引全扫描或索引快速全扫描。
第五,是否用到系统数据字典表或视图。由于系统数据字典表都未被分析过,可能导致极差的"执行计划"。但是不要擅自对数据字典表做分析,否则可能导致死锁,或系统性能下降。
第六,索引列是否函数的参数。如是,索引在查询时用不上。
第七,是否存在潜在的数据类型转换。如将字符型数据与数值型数据比较,ORACLE会自动将字符型用to_number()函数进行转换,从而导致第六种现象的发生。
第 八,是否为表和相关的索引搜集足够的统计数据。对数据经常有增、删、改的表最好定期对表和索引进行分析,可用SQL语句"analyze table xxxx compute statistics for all indexes;"。ORACLE掌握了充分反映实际的统计数据,才有可能做出正确的选择。
第九,索引列的选择性不高。我们假设典型情况,有表 emp,共有一百万行数据,但其中的emp.deptno列,数据只有4种不同的值,如10、20、30、40。虽然emp数据行有很多,ORACLE缺 省认定表中列的值是在所有数据行均匀分布的,也就是说每种deptno值各有25万数据行与之对应。假设SQL搜索条件DEPTNO=10,利用 deptno列上的索引进行数据搜索效率,往往不比全表扫描的高,ORACLE理所当然对索引"视而不见",认为该索引的选择性不高。
但我们考虑 另一种情况,如果一百万数据行实际不是在4种deptno值间平均分配,其中有99万行对应着值10,5000行对应值20,3000行对应值 30,2000行对应值40。在这种数据分布图案中对除值为10外的其它deptno值搜索时,毫无疑问,如果索引能被应用,那么效率会高出很多。我们可 以采用对该索引列进行单独分析,或用analyze语句对该列建立直方图,对该列搜集足够的统计数据,使ORACLE在搜索选择性较高的值能用上索引。
第十,索引列值是否可为空(NULL)。如果索引列值可以是空值,在SQL语句中那些需要返回NULL值的操作,将不会用到索引,如COUNT(*),而是用全表扫描。这是因为索引中存储值不能为全空。
第十一,看是否有用到并行查询(PQO)。并行查询将不会用到索引。
第十二,看PL/SQL语句中是否有用到bind变量。由于数据库不知道bind变量具体是什么值,在做非相等连接时,如"<",">","like"等。ORACLE将引用缺省值,在某些情况下会对执行计划造成影响。
如果从以上几个方面都查不出原因的话,我们只好用采用在语句中加hint的方式强制ORACLE使用最优的"执行计划"。
hint采用注释的方式,有行注释和段注释两种方式。如我们想要用到A表的IND_COL1索引的话,可采用以下方式:"SELECT /*+ INDEX(A IND_COL1)*/ * FROM A WHERE COL1 = XXX;"
注意,注释符必须跟在SELECT之后,且注释中的"+"要紧跟着注释起始符"/*"或"--",否则hint就被认为是一般注释,对PL/SQL语句的执行不产生任何影响。
两种有效的跟踪调试方法 ORACLE提供了两种有效的工具来跟踪调试PL/SQL语句的执行计划。
一种是EXPLAIN TABLE方式。用户必须首先在自己的模式(SCHEMA)下,建立PLAN_TABLE表,执行计划的每一步骤都将记录在该表中,建表SQL脚本为在${ORACLE_HOME}/rdbms/admin/下的utlxplan.sql。
打开SQL*PLUS,输入"SET AUTOTRACE ON",然后运行待调试的SQL语句。在给出查询结果后,ORACLE将显示相应的"执行计划",包括优化器类型、执行代价、连接方式、连接顺序、数据搜索路径以及相应的连续读、物理读等资源代价。
如 果我们不能确定需要跟踪的具体SQL语句,比如某个应用使用一段时间后,响应速度忽然变慢。我们这时可以利用ORACLE提供的另一个有力工具 TKPROF,对应用的执行过程全程跟踪。我们要先在系统视图V$SESSION中,可根据USERID或MACHINE,查出相应的SID和 SERIAL#。以SYS或其他有执行DBMS_SYSTEM程序包的用户连接数据库,执行"EXECUTE DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(SID,SERIAL#,TRUE);"。然后运行应用程序,这时在服务器 端,数据库参数"USER_DUMP_DEST"指示的目录下,会生成ora__xxxx.trc文件,其中xxxx为被跟踪应用的操作系统进程号。
应 用程序执行完成后,用命令tkprof对该文件进行分析。命令示例:"tkprof tracefile outputfile explain=userid/password"。在操作系统ORACLE用户下,键入"tkprof",会有详细的命令帮助。分析后的输出文件 outputfile中,有每一条PL/SQL语句的"执行计划"、CPU占用、物理读次数、逻辑读次数、执行时长等重要信息。根据输出文件的信息,我们 可以很快发现应用中哪条PL/SQL语句是问题的症结所在。

文章二 Oracle基于Client/Server的性能调整
Oracle 数据库广泛应用在社会的各个领域,特别是在Client/Server模式的应用,但是应用开发者往往碰到整个系统的性能随着数据量的增大显著下降的问 题,为了解决这个问题,从以下几个方面:数据库服务器、网络I/O、应用程序等对整个系统加以调整,充分发挥Oracle的效能,提高整个系统的性能。
1 调整数据库服务器的性能
Oracle数据库服务器是整个系统的核心,它的性能高低直接影响整个系统的性能,为了调整Oracle数据库服务器的性能,主要从以下几个方面考虑:
1.1 调整操作系统以适合Oracle数据库服务器运行
Oracle数据库服务器很大程度上依赖于运行服务器的操作系统,如果操作系统不能提供最好性能,那么无论如何调整,Oracle数据库服务器也无法发挥其应有的性能。
1.1.1 为Oracle数据库服务器规划系统资源
据已有计算机可用资源, 规划分配给Oracle服务器资源原则是:尽可能使Oracle服务器使用资源最大化,特别在Client/Server中尽量让服务器上所有资源都来运行Oracle服务。
1.1.2   调整计算机系统中的内存配置
多数操作系统都用虚存来模拟计算机上更大的内存,它实际上是硬盘上的一定的磁盘空间。当实际的内存空间不能满足应用软件的要求时,操作系统就将用这部分 的磁盘空间对内存中的信息进行页面替换,这将引起大量的磁盘I/O操作,使整个服务器的性能下降。为了避免过多地使用虚存,应加大计算机的内存。
1.1.3 为Oracle数据库服务器设置操作系统进程优先级
不要在操作系统中调整Oracle进程的优先级,因为在Oracle数据库系统中,所有的后台和前台数据库服务器进程执行的是同等重要的工作,需要同等的优先级。所以在安装时,让所有的数据库服务器进程都使用缺省的优先级运行。
1.2 调整内存分配
Oracle数据库服务器保留3个基本的内存高速缓存,分别对应3种不同类型的数据:库高速缓存,字典高速缓存和缓冲区高速缓存。库高速缓存和字典高速 缓存一起构成共享池,共享池再加上缓冲区高速缓存便构成了系统全程区(SGA)。SGA是对数据库数据进行快速访问的一个系统全程区,若SGA本身需要频 繁地进行释放、分配,则不能达到快速访问数据的目的,因此应把SGA放在主存中,不要放在虚拟内存中。内存的调整主要是指调整组成SGA的内存结构的大小 来提高系统性能,由于Oracle数据库服务器的内存结构需求与应用密切相关,所以内存结构的调整应在磁盘I/O调整之前进行。
1.2.1 库缓冲区的调整
库缓冲区中包含私用和共享SQL和PL/SQL区,通过比较库缓冲区的命中率决定它的大小。要调整库缓冲区,必须首先了解该库缓冲区的活动情况,库缓冲 区的活动统计信息保留在动态性能表v$librarycache数据字典中,可通过查询该表来了解其活动情况,以决定如何调整。
Select sum(pins),sum(reloads) from v$librarycache;
Pins列给出SQL语句,PL/SQL块及被访问对象定义的总次数;Reloads列给出SQL 和PL/SQL块的隐式分析或对象定义重装载时在库程序缓冲区中发生的错误。如果sum(pins)/sum(reloads) ≈0,则库缓冲区的命中率合适;若sum(pins)/sum(reloads)>1, 则需调整初始化参数 shared_pool_size来重新调整分配给共享池的内存量。
1.2.2 数据字典缓冲区的调整
数据字典缓冲区包含了有关数据库的结构、用户、实体信息。数据字典的命中率,对系统性能影响极大。数据字典缓冲区的使用情况记录在动态性能表v$librarycache中,可通过查询该表来了解其活动情况,以决定如何调整。
Select sum(gets),sum(getmisses) from v$rowcache;
Gets列是对相应项请求次数的统计;Getmisses 列是引起缓冲区出错的数据的请求次数。对于频繁访问的数据字典缓冲区,sum(getmisses)/sum(gets)<10%~15%。若大于 此百分数,则应考虑增加数据字典缓冲区的容量,即需调整初始化参数shared_pool_size来重新调整分配给共享池的内存量。
1.2.3 缓冲区高速缓存的调整
用户进程所存取的所有数据都是经过缓冲区高速缓存来存取,所以该部分的命中率,对性能至关重要。缓冲区高速缓存的使用情况记录在动态性能表v$sysstat中,可通过查询该表来了解其活动情况,以决定如何调整。
Select name,value from v$sysstat
where name in ('dbblock gets','consistent gets','physical reads');
dbblock gets和consistent gets的值是请求数据缓冲区中读的总次数。physical reads的值是请求数据时引起从盘中读文件的次数。从缓冲区高速缓存中读的可能性的高低称为缓冲区的命中率,计算公式:
Hit Ratio=1-(physical reds/(dbblock gets+consistent gets))
如果Hit Ratio<60%~70%,则应增大db_block_buffers的参数值。db_block_buffers可以调整分配给缓冲区高速缓存 的内存量,即db_block_buffers可设置分配缓冲区高速缓存的数据块的个数。缓冲区高速缓存的总字节数=db_block_buffers的 值*db_block_size的值。 db_block_size 的值表示数据块大小的字节数,可查询 v$parameter 表:select name,value from v$parameter where name='db_block_size';
在修改了上述数据库的初始化参数后,必须先关闭数据库,在重新启动数据库后才能使新的设置起作用。
1.3 调整磁盘 I/O
磁盘的I/O速度对整个系统性能有重要影响。解决好磁盘I/O问题,可显著提高性能。影响磁盘I/O的性能的主要原因有磁盘竞争、I/O次数过多和数据块空间的分配管理。
为Oracle数据库服务器创建新文件时,不论是表空间所用的数据文件还是数据事务登录所用的日志文件,都应仔细考虑数据库服务器上的可用磁盘资源。如 果服务器上有多个磁盘,则可将文件分散存储到各个可用磁盘上,减少对数据库的数据文件及事务日志文件的竞争,从而有效地改善服务器的性能。对于不同的应用 系统都有各自的数据集,应当创见不同的表空间分别存储各自应用系统的数据,并且尽可能的把表空间对应的数据文件存放在不同的磁盘上,这种从物理上把每个应 用系统的表空间分散存放的方法,可以排除两个应用系统竞争磁盘的可能性。数据文件、事务日志文件分别存放在不同的磁盘上,这样事务处理执行的磁盘访问不妨 碍对相应的事物日志登记的磁盘访问。如果有多个磁盘可用,将两个事物日志成员放在不同的磁盘驱动器上,就可以消除日志文件可能产生的磁盘竞争。应把一个应 用的表数据和索引数据分散存放不同表空间上,并且尽量把不同类型的表空间存放在不同磁盘上,这样就消除了表数据和索引数据的磁盘竞争。
1.4 调整数据库服务器的回滚段
回滚段是一个存储区域,数据库使用该存储区域存放曾经由一个事务更新或删除的行的原始数据值。如果用户要回滚一个事务所做的改变,那么数据库就从回滚段 中读回改变前的数据并使该事务影响的行改变为它们的原状态。回滚段控制着数据库处理事务的能力,因而在数据库成功中起着关键性的作用,不管数据库的其它部 分设计得多好,如果它设计得不合理,将会严重影响系统的性能。建立和调整回滚段的原则如下。
1.4.1 分离回滚段
分离回滚段是指单 独为回滚段创建一个以上的表空间,使回滚段与数据字典、用户数据、索引等分离开来。由于回滚段的写入与数据和索引的写入是并行进行的,因此将它分离出来可 以减少I/O争用。如果回滚段与数据不分离,倘若要某个表空间脱机或撤消,那么在该表空间中的各个回滚段没有全部脱机之前,不能将这个表空间脱机或撤消。 而一旦该表空间不可用,则该表空间中的所有回滚段也不能使用,这将浪费所有分配的磁盘空间。所以,独立回滚段可使数据库管理变得容易。回滚段的经常性收 缩,使得表空间的自由块更容易形成碎片。分离回滚段可以减少数据库表空间的碎片产生。
1.4.2 创建不同大小的回滚段群
对于一些联 机事物处理,他们一般是频繁地对少量数据进行修改,创建许多小的回滚段对之有利。每一个事物的入口项只能限于一个回滚段,回滚段应该充分大以容纳一个完整 的事物处理,因此对一些较大型事物,需要较大型的回滚段。极个别脱机处理事物会产生大量的回滚信息,这时需要一个特大号的回滚段来处理。根据这些理论,在 Oracle数据库服务器中针对上述3种事物处理创建三组:小事物组、较大事物组、特大事物组等大小不同的回滚段群,并且将之分散到3个不同的表空间上, 群内大小相同,应能满足该组事物处理的最大要求。
1.4.3 创建数量适当的回滚段
一般回滚段数量与并发事物个数有关,以下给出由于并发事物个数而应建立回滚段的参考数:
并发事物(n)   回滚段数
n<16        4
16 ≤ n<32      8
n≥ 32      n/4
2 调整 Client/Server 模式下的网络 I/O
Client/Server环境中的应用处理是分布在客户应用程序和数据库服务程序之间的。在 Client/Server环境中Client与Server之间的网络I/O是整个系统性能提高的瓶颈,一个客户应用程序引起的网络I/O越少,应用及 整个系统的性能越好。减少网络I/O的最重要的一条原则:将应用逻辑集中在数据库服务器中。
2.1 使用Oracle数据库的完整约束性
当为应用建表时,应当为一些有特殊要求的数据加上适当的完整性约束,这样就能实现由数据库本身而不是应用程序来约束数据符合一定的条件。数据库服务器端 的完整约束的执行操作是在比SQL语句级别更低的系统机制上优化,它与客户端无关,只在服务器中运行,不需在Client 端和Server端之间传递SQL语句,有效地减轻网络I/O负担。
2.2 使用数据库触发器
完整约束性只能实现一些较简单的数据约 束条件,对一些较复杂的事物处理规则就无能为力,这时最好不要在应用程序中实施复杂的程序控制,而是应当采用数据库触发器来实施复杂的事物规则。数据库触 发器能实现由数据库本身,而不是应用程序,来约束数据符合复杂的事物处理规则,并且容易创建,便于管理,避免大量的网络I/O。
例如:将当前表A中成为历史的记录从A表中转储到历史表B中,表示为Lsbs。
在应用程序中实现:          用数据库触发器实现:
Beign               Create trigger delete1
    Update A set lsbs='T';       After update of lsbs on A
    Insert into B            For each row
    Select * from A where lsbs='T';     Insert into B
    Delete A where lsbs='T';         select * from A where :new.lsbs='T';
End;                 Delete A where :new.lsbs='T';
      End delete1;
在应用程序中实现时,所有的SQL命令请求传送的数据都要通过网络在Client端和Server端进行交换,而不像数据库触发器一样,SQL本身在 Server端,不需要通过网络传输数据。当进行操作的数据量相当大时,并且多个用户同时操作时,通过在应用程序中实现复杂的控制,必将增大网络I/O的 负荷,使整个系统的性能降低,而用数据库触发器能完全避免这种情况发生。
2.3 使用存储过程、存储函数和包
Oracle的存储过程 和存储函数是命名的能完成一定功能并且存储在Server端的PL/SQL的集合。包是一种把有关的过程和函数组织封装成一个数据库程序单元的方法。它们 相对于应用程序的过程、函数而言,把SQL命令存储在Server端。使用存储过程和存储函数,应用程序不必再包含多个网络操作的SQL语句去执行数据库 服务器操作,而是简单调用存储过程和存储函数,在网络上传输的只是调用过程的名字和输出结果,这样就可减少大量的网络I/O。
例如:基表A、B的定义:name char(20);detail char(10);A表100万记录,应用程序将从基表A中检索detail列符合给出条件的记录,并将之插入基表B。
如果在Developer/2000 From中按钮触发器直接用PL/SQL实现和把它改写为一个Oracle存储过程,然后在From中调用此过程实现比较,后者性能显著提高。
在考虑使用上述3种方法时:首先考虑使用完整约束性。对于数据库触发器和存储过程,如果需要所有访问数据库的程序自动实施一定规则或检查,那么使用数据库触发器;如果只需对少数的程序实施一定的规则或检查,则可创建一个过程,让有关程序调用这个过程。
3 应用程序的调整
3.1 SQL语句的优化
SQL语句的执行速度,可以受很多因素的影响而变化。但主要的影响因素是:驱动表、执行操作的先后顺序和索引的运用。可以由很多不同的方法间接地改变这些因素,以达到最优的执行速度。这里主要探讨当对多个表进行连接查询时应遵循的优化原则:
(1) 用于连接的子句的列应被索引、在Where子句中应尽量利用索引,而不是避开索引。
(2) 连接操作应从返回较少行上驱动。
(3) 如果所连接的表A和B,A表长度远远大于B表,建议从较大的A表上驱动。
(4) 如果Where子句中含有选择性条件,Where No=20,将最具有选择性部分放在表达式最后。
(5) 如果只有一个表有索引,另一表无索引,无索引的表通常作为驱动表。如A表的No列以被索引,而B表的No 列没被索引,则应当B表作为驱动表,A表作为被驱动表。
(6) 若用于连接的列和Where子句中其他选择条件列均有索引,则按各个索引对查询的有效性和选择性分别定出级别,结合表中具体数据构成情况,从中选出优化路径,一般需要考虑:子句中哪些列可以使用索引、哪些索引具有唯一性及被查询表行数目等。
3.2 建立和使用视图、索引
利用视图可以将基表中的列或行进行裁减、隐藏一部分数据,并且能够将涉及到多个表的复杂查询以视图的方式给出,使应用程序开发简洁快速。利用索引可以提 高查询性能,减少磁盘 I/O,优化对数据表的查询,加速SQL语句的执行。但任何时候建立索引都能提高性能,何时建立索引应当遵循以下原则:该表常用来在索引列上查询,该表不 常更新、插入、删除等操作,查询出来的结果记录数应控制在原表的2%~4% 。
3.3 使用 Oracle 的数组接口
当一个客户应 用程序插入一行或用一个查询来向服务器请求某行时,不是发送具有单个行的网络包,而是采用数组处理,即把要插入的多个行或检索出的多个行缓冲在数组中,然 后通过很少的几个包就可在网上传送这些数组。例如,一个给定的Select语句返回2000行数据,每行平均大小为40个字节,数据包的大小为4kB,而 数组大小参数(arraysize)设置为20 ,则需从服务器发送100个数据包到客户机。如果简单地把(arraysize)设置为2000,那么同样的操作只需要传送 20个数据包。这样就减少了网络的传输量,提高了所有应用的性能。
4 总结
我们在开发应用程序时,遵循上述的方法和原则,对系统进行调整,收到了令人满意的效果。但是应当指出,由于客户机、网络、服务器这3个相互依存的组成部分都必须调整和同步才能产生最佳的性能,因此还应根据系统的具体情况,具体分析和调整。