PLSQL程序优化和性能测试技巧

上传人:daj****de2 文档编号:149058769 上传时间:2022-09-06 格式:DOCX 页数:29 大小:943.32KB
返回 下载 相关 举报
PLSQL程序优化和性能测试技巧_第1页
第1页 / 共29页
PLSQL程序优化和性能测试技巧_第2页
第2页 / 共29页
PLSQL程序优化和性能测试技巧_第3页
第3页 / 共29页
点击查看更多>>
资源描述
文件编号:版本号更改条款及内容更改人审批人更改日期1. 前言31.1目的31.2文档说明31.3词汇表41.4参考资料42. PLSQL程序优化原则42.1导致性能问题的内在原因42.2 PLSQL优化的核心思想42.3 ORACLE 优化器 52.4 PLSQL 优化 62.4.1选择最有效率的表名顺序62.4.2 WHERE子句中的连接顺序62.4.3 SELECT子句中避免使用 * 2.4.4 用 EXISTS 替代 IN72.4.5 用 NOT EXISTS 替代 NOT IN72.4.6用表连接替换EXISTS82.4.7 用 EXISTS 替换 DISTINCT82.4.8减少对表的查询92.4.9避免循环(游标)里面嵌查询92.4.10 尽量用 union all 替换 union112.4.11使用DECODE函数来减少处理时间112.4.12 group by 优化 112.4.13尽量避免用order by122.4.14用Where子句替换HAVING子句122.4.15使用表的别名(Alias)122.4.16删除重复记录122.4.17 COMMIT 使用 132.4.18减少多表关联132.4.19批量数据插入132.5索引使用优化142.5.1避免在索引列上使用函数或运算142.5.2避免改变索引列的类型.152.5.3避免在索引列上使用NOT152.5.4 用=替代152.5.5避免在索引列上使用IS NULL和IS NOT NULL162.5.6带通配符()的like语句162.5.7总是使用索引的第一个列162.5.8多个平等的索引172.5.9不明确的索引等级172.5.10自动选择索引172.5.11 使用提示(Hints)172.5.12表上存在过旧的分析182.5.13表上存在并行182.5.14关于索引建立183. PLSQL程序性能问题测试方法193.1性能问题分析193.2 Expain Plan分析索引使用203.3 TOPSQL 分析 213.4针对性语句搜索253.5后台存储过程跟踪263.6性能监控错误!未定义书签。4. 性能测试工具设计思想错误!未定义书签。1.前言1.1目的性能测试是测试中比较重要的工作,性能测试应分为压力的测试和性能的测试,其中性 能问题中绝大部分都是由于程序编写的不合理、不规范造成的。本文档说明了程序中常见的 不优化的脚本编写,导致的性能问题,并且在也描述了怎样去跟踪和解决程序上的性能问题 的方法。在最后一章里面描述了做一个白盒测试工具测试性能问题的设计思想。1.2文档说明本文档只说明PLSQL编写的优化问题,不包括 ORACLE本身的性能优化(内存 SGA、系统参数、表空间等)、操作系统的性能问题和硬件的性能问题。对于PLSQL程序 优化方面的内容有很多,本文档列出在我们实际工作中一些常见的情况。本文档难免有不正 确的地方,也需要大家给予指正。本文档举例说明的问题语句不是实际程序中真正存在的,只是让大家能看起来更容易理 解,但这些语句也不代表在我们程序中其他部分语句不存在这些问题。举例说明中的语句采用的是社保核心平台的数据字典,在举例描述中没有标明表名和字 段名的含义,还需单独参考。1.3词汇表词汇名称词汇含义备注1.4参考资料编号资料名称作者日期出版单位1ORACLE SQL性能优化系列232. PLSQL程序优化原则2.1导致性能问题的内在原因导致系统性能出现问题从系统底层分析也就是如下几个原因: CPU占用率过高,资源争用导致等待内存使用率过高,内存不足需要磁盘虚拟内存 IO占用率过高,磁盘访问需要等待2.2 PLSQL优化的核心思想PLSQL优化实际上就是避免出现“导致性能问题的内在原因”,实际上编写程序,以 及性能问题跟踪应该本着这个核心思想去考虑和解决问题。 PLSQL程序占用CPU的情况系统解读SQL语句执行,会消耗CPU的使用运算(计算)会消耗CPU的使用 PLSQL程序占用内存的情况读写数据都需要访问内存内存不足时,也会使用磁盘 PLSQL程序增大IO的情况读写数据都需要访问磁盘IO读取的数据越多,IO就越大大家都知道CPU现在都很高,计算速度非常快;访问内存的速度也很快;但磁盘的访 问相对前两个相比速度就差的非常大了,因此PLSQL性能优化的重点也就是减少IO的瓶 颈,换句话说就是尽量减少IO的访问。性能的优先级CPU-内存-IO,影响性能的因素依次递增。根据上面的分析,PLSQL 优化的核心思想为:1. 避免过多复杂的SQL脚本,减少系统的解读过程2. 避免过多的无用的计算,例如:死循环3. 避免浪费内存空间没有必要的SQL脚本,导致内存不足4. 内存中计算和访问速度很快5. 尽可能的减少磁盘的访问的数据量,该原则是PLSQL优化中重要思想。6. 尽可能的减少磁盘的访问的次数,该原则是PLSQL优化中重要思想。下面的章节具体介绍常见影响性能的SQL语句情况。2.3 ORACLE优化器ORACLE的优化器:a. RULE (基于规则)b. COST (基于成本)c. CHOOSE (选择性)设置缺省的优化器,可以通过对init.ora文件中OPTIMIZER_MODE参数的各种声明,如 RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS .你当然也在 SQL 句级或是会话 (session) 级 对 其 进 行 覆 盖 .为了使用基于成本的优化器(CBO, Cost-Based Optimizer),你必须经常运行analyze命令, 以增加数据库中的对象统计信息(object statistics)的准确性.如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的优化器模式将和是否运 行过analyze命令有关.如果table已经被analyze过,优化器模式将自动成为CBO ,反之, 数 据 库 将 采 用 RULE 形 式 的 优 化 器 . 在缺省情况下,ORACLE采用CHOOSE优化器,为了避免那些不必要的全表扫描(full table scan),你必须尽量避免使用CHOOSE优化器,而直接采用基于规则或者基于成本的 优化器.在oracle10g前默认的优化模式是CHOOSE, 10g默认是ALL_ROWS,我不建议大家 去改动ORACLE的默认优化模式。2.4 PLSQL 优化主要说明了在SQL编写上和PLSQL程序编写上可以优化的地方。2.4.1选择最有效率的表名顺序只在基于规则的优化器rule中有效,目前我们oracle选择的优化器基本都不选择rule,因此该问题基 本不会出现,但为了安全和规范起见,建议编程习惯采用该规则。ORACLE的解读器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表 (基础表driving table)将被最先处理.在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表 作为基础表.当ORACLE处理多个表时,会运用排序及合并的方式连接它们.首先,扫描第一个表(FROM子 句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二 个表中检索出的记录与第一个表中合适记录进行合并.例如:表表ac01ab01有有16,3841条 条记 记录录选择ab01作为基础表( 好 的方法)selectcount(*)fromac01,ab01执行时间0.96秒选 择ac01作为基础表(不好的方法)select count(*) from ab01,ac01 执行时间 26.09 秒2.4.2 WHERE子句中的连接顺序ORACLE采用自下而上的顺序解读WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE 条件之前 例如:(低效)SELECTab01.aab001,ab02.aab051FROMab01,ab02WHERE ab02.aae140=31AND ab01.aab001=ab02.aab001。)ab01,ab02(高效SELECTab01.aab001,ab02.aab051FROMWHERE ab01.aab001=ab02.aab001 AND ab02.aae140=31。2.4.3 SELECT子句中避免使用 * 当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用*是一个方便的方法.不幸 的是,这是一个非常低效的方法.实际上,ORACLE在解读的过程中,会将*依次转换成所有的列名,这个工 作是通过查询数据字典完成的,这意味着将耗费更多的时间。2.4.4 用 EXISTS 替代 IN实际情况看,使用exists替换in效果不是很明显,基本一样。在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下,使用EXISTS( 或 NOT EXISTS) 通 常 将 提 高 查 询 的 效 率 .SELECT*FROM ac01Where aac001 in (select aac001 from ac02 where aab001=str_aab001 and aae140=31)。或SELECT*FROM ac01Where aac001 in (select distinct aac001 from ac02 where aab001=str_aab001 and aae140=31)。注 意 使 用 distinct 也 会 影 响 速 度高效:SELECT*FROM ac01Where exists (select 1 from ac02 where aac001=ac01.aac001 and aab001=str_aab001 and aae140=31)。in的常量列表是优化的(例如:aab019 in (20,30),不用exists替换;in列表相当于or2.4.5 用 NOT EXISTS 替代 NOT INOracle在10g之前版本not in都是最低效的语句,虽然在10g上not in做到了一些改进,但仍然还是存在 一些问题,因此我们一定要使用not exists来替代not in的写法。在子查询中,NOT IN子句将执行一个内部的排序和合并.无论在哪种情况下,NOT IN都是最低效的(因为它 对子查询中的表执行了一个全表遍历).为了避免使用 NOT IN,我们可以把它改写成 NOT EXISTS.例如:SELECT*FROMac01WHERE aab001 NOT IN (SELECT aab001 from ab01 whereaab020=100)。为了提高效率.改写为:SELECT*FROMac01WHERE not exists (SELECT 1 from ab01 where aab001=ac01.aab001 and aab020三 100)。2.4.6用表连接替换EXISTS在子查询的表和主表查询是多对一的情况,一般采用表连接的方式比EXISTS更有效率。例如:低效:SELECTac01.*FROMac011fromac02aac001=ac01.aac001 aab001=ac01.aab001 aae140=31SELECTac01.*ac02,ac01 ac02.aac001=ac01.aac001 ac02.aab001=ac01.aab001 ac02.aae140=31Whereexists(selectwhere and and and aae041=200801)。 高效:FROMWhereand and and aae041=200801。到底exists和表关联哪种效率高,其实是根据两个表之间的数据量差别大小是有关的,如果差别不大实际 上速度基本差不多。2.4.7 用 EXISTS 替换 DISTINCT当提交一个包含一对多表信息(比如个人基本信息表和个人参保信息表)的查询时,避免在SELECT子句 中 使 用 DISTINCT. 一 般 可 以 考 虑 用 EXISTS 替 换例如:低效:selectdistinctac01.aac001fromac02,ac01whereac02.aac001=ac01.aac001andac02.aae140=31andac01.aab001=100100。高效:selectac01.aac001fromac01whereexists(select1fromac02whereaac001=ac01.aac001andaae140=31)and ac01.aab001=100100。EXISTS使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后, 立刻返回结果。因此如果不是特别研究和追求速度的话(例如:数据转换),查询一个表的数据需要关 联其他表的这种情况查询,建议采用EXISTS的方式。2.4.8减少对表的查询该问题是我们编程中出现过的问题,请大家一定注意,并且该类问题优化可以带来较大性能的提 升。例如:低效 cursor cur_kc24_mz isSelect akc260from kc24where akb020 =str_akb020and aka130=11。cursor cur_kc24_zy isSelect akc260from kc24where akb020 =str_akb020and aka130=21。for rec_mz in cur_kc24_mz loop门诊处理.end loop。for rec_mz in cur_kc24_zy loop住院处理.end loop。高效 cursor cur_kc24 isSelect akc260,aka130from kc24where akb020 =str_akb020and aka130 in (11,21)。for rec_kc24 in cur_kc24 loopif rec_kc24.aka130=11 then门诊处理.end if。if rec_kc24.aka130=21 then住院处理.end if。end loop。高效的做法使用同样的条件(或者说是索引)只访问一次磁盘,低效的做法访问了 2次磁盘,这样速度 差别将近2倍。2.4.9避免循环(游标)里面嵌查询游标里面不能嵌入查询(或者再嵌游标),其实也不能有update delete等语句,只能有insert语句。但在实 际的编程情况下是不可能完全避免的,但我们一定要尽量避免。该类问题也是我们程序中出现过的问题,该类问题也可以大大提升程序效率,请大家一定注意。例如:低效:Cursor cur_ac04 isSelect aac001,akc010From ac04Where aab001= prm_aab001。For rec_ac04 in cur_ac04 loopSelect aac008Into str_aac008from ac01where aac001=rec_ac04.aac001。if str_aac008= 1 thenn_jfje := rec_ac04.akc010*0.08。end if。if str_aac008=2 thenn_jfje := rec_ac04.akc010*0.1。end if。End loop。高效:Cursor cur_ac04 isSelect ac01.aac001,ac04.akc010,ac01.aac008From ac04,ac01Where ac04.aac001=ac01.aac001and aab001= prm_aab001。For rec_ac04 in cur_ac04 loopif rec.aac008=T thenn_jfje := rec_ac04.akc010*0.08。end if。if rec.aac008=2 thenn_jfje := rec_ac04.akc010*0.1。end if。end loop。优化的方法是尽量把游标循环中的查询语句放到游标查询中一起查询出来,这样相当于只访问了 1次磁 盘读到内存;如果放到游标中的话,假如游标有100万数据量,那么程序需要100万次磁盘,可以想象 浪费了多少IO的访问。如果在程序编写上没有办法避免游标中有查询语句的话(一般情况是可以避免的),那么也要保证游标 中的查询使用的索引(即查询速度非常快),例如:游标100万数据量,游标中的查询语句执行需要0.02秒,从这个速度上来说是很快的,但总体上看100万*0.02秒=2万秒=5小时33分钟,如果写一个不 够优化的语句需要1秒,那么需要几天能执行完呢?2.4.10 尽量用 union all 替换 unionUnion会去掉重复的记录,会有排序的动作,会浪费时间。因此在没有重复记录的情况下或可以允许有重 复记录的话,要尽量采用union all来关联。2.4.11使用DECODE函数来减少处理时间使用 DECODE函数可以避免重复扫描相同记录或重复连接相同的表.例如:(低效)select count(1) from ac01 where aab001=100001 and aac008=1。select count(1) from ac01 where aab001=100001 and aac008=2(低效)Select count(1),aac008From ac01Where aab001=100001and aac008 in (1,2)group by aac008。(高效)select count(decode(aac008,1,1,null) zz,count(decode(aac008,2, 1 ,null) txfrom ac01where aab001=100001。特别说明:group by和order by都会影响性能,编程时尽量避免没有必要的分组和排序,或者通过其他的有效的编程 办法去替换,比如上面的处理办法。2.4.12 group by 优化Group by需要查询后排序,速度慢影响性能,如果查询数据量大,并且分组复杂,这样的查询语句在性 能上是有问题的。尽量避免使用分组或者采用上面的一节的办法去代替。采用group by的也一定要进行优化。例如:低效selectac04.aac001,ac01.aac002,ac01.aac003,sum(aac040),ac01.aab001fromac04,ac01whereac04.aac001=ac01.aac001andac01.aab001=1000000370group by ac04.aac001,ac01.aac002,ac01.aac003,ac01.aab001。高效:selectac04.aac001,ac01.aac002,ac01.aac003,gzze,ac01.aab001from (select aac001,sum(aac040) gzze from ac04 group by aac001)ac04,ac01whereac04.aac001=ac01.aac001and aab001=1000000370。2.4.13尽量避免用order byOrder by需要查询后排序,速度慢影响性能,如果查询数据量大,排序的时间就很长。但我们也不能避免 不使用,这样大家一定注意一点的是如果使用order by那么排序的列表必须符合索引,这样在速度上会得 到很大的提升。2.4.14用Where子句替换HAVING子句避免使用HAVING子句,HAVING只会在检索出所有记录之后才对结果集进行过滤.这个处理需要排序,总计等操作.如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销.例如:低效:SELECTaac008,count(1)FROMac01GROUPBYaac008HAVINGaac008in(1,2)。高效SELECT aac008,count(1)FROM ac01Whereaac008in(1,2)GROUP BY aac008。HAVING中的条件一般用于对一些集合函数的比较,如COUNT()等等.除此而外,一般 的条件应该写在WHERE子句中2.4.15使用表的别名(Alias)当在SQL语句中连接多个表时,请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解 读的时间并减少那些由Column歧义引起的语法错误.2.4.16删除重复记录一般数据转换的程序经常会使用到该方法。最高效的删除重复记录方法 (因为使用 了 ROWID)DELETEFROMac01aWHEREa.rowid(SELECTMIN(b.rowid)FROMac01bWHERE a.aac002=b.aac002and a.aac003=b.aac003 )。2.4.17 COMMIT 使用数据转换的程序需要关注这一点。1. Commit执行也是有时间的,不过时间特别短,但提交频率特别大,必然也会浪费时间。2.commit可以释放资源,在大量数据更新时,必须及时提交。a.回滚 段 上 用 于 恢 复 数 据 的 信 息 .b.被程序语句获得的锁c.redologbuffer中的空间d. ORACLE为管理上述3种资源中的内部花费例如:Cur_ac20有5000万数据n_count :=0。For arec in cur_ac20 loopInsert into ac20n_count := n_count + 1。If n_count = = 100000 then -10 万一提交commit。n_count := 0。End if。End loop。Commit。如果1条一提交,需要提交5000万必然浪费时间;如果整体提交,资源不能释放,性能必须下降。在实际编程时,应注意提交的次数和提交的数据量的平衡关系。2.4.18减少多表关联表关联的越多,查询速度就越慢,尽量减少多个表的关联,建议表关联不要超过3个(子查询也属于表 关联)。数据转换上会存在大数据量表的关联,关联多了会影响索引的效率,可以采用建立临时表的办法,有时 更能提高速度。2.4.19批量数据插入数据转换时或者大业务数据插入时,有以下几种办法进行数据插入(不包括imp、impdp和sqlloader)Insert into . select 方式将查询的结果一次插入到目标表中。例如:Insert into ac01_bak select * from ac01。由于是一次查询一次插入,并且最后一次提交,他的速度要比下面描述的curosr的方式速度要快。但查 询插入的数据量过大必然会占用更多的内存和undo表空间,只能在插入完成后提交,这样资源不能释 放,会导致回滚表空间不足和快照过旧的问题,另外一旦失败需要全部回滚。因此建议小数据量(例 如:300万以下)的导入采用该种方式。 Insert /*+append */ into . select 方式该种方式同上种方式,不过由于有append的提示,这种语句不走回滚段直接插入数据文件,速度非常 快。注意系统开发编程不能使用该种方式,数据转换可以灵活使用。 Cursor 方式定义游标,然后逐行进行插入,然后定量提交。例如:Cusor cur_ac20 isSelect * from ac20。 n_count :=0。For rec_ac20 in cur_ac20 loopInsert into ac20_bak(aac001,.)Values(rec_ac20.aac001,.)。If n_count :=100000 thenCommit。n_count :=0。End if。End loop。 批绑定的方式通过游标查询将数据逐行写到数组里(实际上就是内存),然后通过批绑定的语句 forall . in.insert into.values.。将内存的数据一次写入到数据文件中。相比cursor的方式减少了对io的访问次数,提高 了速度,但注意内存别溢出了。2.5索引使用优化在实际的应用系统中索引问题导致性能问题可能能占到80%,在程序优化上索引问题是需要我们特别关 注的。本节主要描述什么情况索引会不生效。2.5.1避免在索引列上使用函数或运算这个问题是在我们实际编程中出现过的,请大家一定注意。在索引列上使用函数或运算,查询条件都不 会使用索引。例如:不使用索引Select * from ka02 where aka060=10001000 and to_char(aae030,yyyymm)=200801。使用索引Select * from ka02 where aka060=10001000 and aae030=to_date(200801,yyyymm)。不使用索引Select * from ka02 where aka060=10001000 and aae031+1=sysdate。使用索引Select * from ac04 where aac001=10001000 and aae031=sysdate -1。如果一定要对使用函数的列启用索引 ,ORACLE新的功能:基于函数的索引(Function-Based Index) CREATE INDEX IDX_KA02_AKA066 ON KA02 (UPPER(AKA066)。/* 建立基于函数的索引 */SELECT * FROM KA02 WHERE UPPER(AKA066) = ASPL。/*将使用索引 */不是极特殊情况,建议不要使用。2.5.2避免改变索引列的类型.索引列的条件如果类型不匹配,则不能使用索引。例如:不使用索引Select * from ac01 where aac001=10001000。使用索引Select * from ac01 where aac001=10001000。2.5.3避免在索引列上使用NOT避免在索引列上使用NOT, NOT不会使查询条件使用索引。对于!=这样的判断也是不能使用索引的,索引 只能告诉你什么存在于表中,而不能告诉你什么不存在于表中例低 效 :( 这 里select *From ac02Wherenot高 效 :( 这 里select *From ac02Where aab019 in (20,30)。2.5.4用=替代虽然效果不是特别明显,但建议采用这种方式 低SELECTFROMWHERE如:不使用索引)aab019=10。使 用 了 索 引 )效:*aab019ab0110高效:SELECT*FROMab01WHERE aab019 =20两者的区别在于,前者DBMS首先定位到aab019=10的记录并且向前扫描到第一个 aab019大于10的记录,而后者DBMS将直接跳到第一个aab019等于10的记录2.5.5避免在索引列上使用IS NULL和IS NOT NULL对于索引列使用is null或is not null不会使用上索引.因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使 ORACLE停用该索引.举例:低效:(索引失效)select*fromab01whereaab019isnotnull。高效:(索引有效)select * from ab01 where aab019 in(10,20,30)。在实际开发中,对于这类的问题很难避免,如果不是特别影响速度或者要求速度的,可以忽略。2.5.6带通配符(%)的like语句%在常量前面索引就不会使用。例如:不使用索引Select * from ac01 where aac002 like 210104。Select * from ac01 where aac002 like 210104%。使用索引Select * from ac01 where aac002 like 210104%。2.5.7总是使用索引的第一个列如果索引是建立在多个列上,只有在它的第一个列被where子句引用时,优化器才会选择使用该索引。例如:Ac02 的复合索引:aac001、aae140、aae041Select * from ac02 where aae140=31 and aae041=200801。-不会使用索引Select * from ac02 where aac001=10001000。-可以使用索引如果不使用索引第一列基本上不会使用索引,使用索引要按照索引的顺序使用,另外使用复合索引的列越多,查询的速度就越快2.5.8多个平等的索引当SQL语句的执行路径可以使用分布在多个表上的多个索引时,ORACLE会同时使用多个索引并在运行 时对它们的记录进行合并,检索出仅对全部索引有效的记录.在ORACLE选择执行路径时,唯一性索引的等级高于非唯一性索引.然而这个规则只有当WHERE子句中索引列和常量比较才有效.如果索引列和其他表的索引类相比较.这种子句在优化器中的 等级是非常低的.如果不同表中两个相同等级的索引将被引用,FROM子句中表的顺序将决定哪个会被率先使用.FROM子 句 中 最后 的表 的索 引 将有最高 的优先级 .如果同一表中有两个相同等级的索引被引用,oracle会分析最有效的索引去引用,其他的索引不会使用, 如果这些相同等级的索引效果差不多,oracle可能会自动合并进行使用。2.5.9不明确的索引等级当ORACLE无法判断索引的等级高低差别,优化器将只使用一个索引,它就是在WHERE子句中被列在最 前面的.2.5.10自动选择索引如果表中有两个以上(包括两个)索引,其中有一个唯一性索引,而其他是非唯一性.在这种情况下,ORACLE将使用唯一性索引而完全忽略非唯一性索引.2.5.11 使用提示(Hints)对于表的访问,可以使用两种 FULL hint告诉ORACLE使用全表扫描的方式访问指定表.Hints. FULL和ROWID例如:SELECT/*+FULL(AC01)*/*FROMAC01WHEREAAC001=10001000o如果一个大表没有被设定为缓存(CACHED)表而你希望它的数据在查询结束是仍然停留 在SGA中,你就可以使用CACHE hint来告诉优化器把数据保留在SGA中.通常CACHE hint和FULL hint 一起使用.例如:SELECT/*+FULL(AC01)CACHE(AC01)*/AC01FROMROWID hint 告诉 ORACLE 使用 TABLE ACCESS BY ROWID 的操作访问表.采用 TABLE ACCESS BY ROWID的方式特别是当访问大表的时候,使用这种方式,你需要知道ROIWD的值或者使用索引.索引hint 告诉ORACLE使用基于索引的扫描方式.你不必说明具体的索引名称例如:SELECT/*+index(IDX_AC01_AAC002)*/aac001FROMAC01WHERE aac002=210111111111111111。在不使用hint的情况下,以上的查询应该也会使用索引,然而,如果 该索引的重复值过多而你的优化器是CBO,优化器就可能忽略索引.在这种情况下,你可以用INDEX hint 强制ORACLE使用该索引.ORACLE hints 还包括 ALL_ROWS, FIRST_ROWS, RULE,USE_NL, USE_MERGE, USE_HASH 等等.使用hint ,表示我们对ORACLE优化器缺省的执行路径不满意,需要手工修改. 这是一个很有技巧性的工作.除非特定的情况,例如:数据转换,其他情况最好不用.2.5.12表上存在过旧的分析我们现在很多工程都存在性能问题,其中有很多种情况都是由于分析过旧导致ORACLE判断索引级别和 资源成本上出现问题,会导致ORACLE判断错误不使用索引。我个人觉得这是ORACLE不够完善的地 方。解决办法:第一种办法:删除分析,停止oracle10g的自动分析,但不使用分析,oracle访问数据的CPU消耗就 过大。第二种办法:重新分析,但过长时间后,索引是否会再次失效,没有验证过。2.5.13表上存在并行表上存在并行,ORACLE判断索引级别和资源成本上出现问题,会导致ORACLE判断错误不使用索引。这个问题我不知道有什么好的处理办法,从现场实际应用速度角度比较,我还是选择去掉并行,因为不 使用索引进行全表扫描肯定是不能忍受的。2.5.14关于索引建立索引的使用是肯定会大大提高查询的速度,但索引其实也是一种数据,它也是存放的用户类型的表空间 下的,索引建立的越多越大,占用的空间也越大,从用户的环境来说这也不是问题,但如果一个表有过 多过大的查询,必然会影响insert、delete和update索引列的速度,因为这些操作改变了整个表的索引顺 序,oracle需要进行调整,这样性能就下降了。因此我们一定要合理的建立好有效的索引,编程也要符合 索引的规则,而不能是索引符合编程的规则。案例:某工程数据转换,采用游标循环insert的方式,总共2000万的数据,总共用了 4个小时,原因就是目标 表里面有很多索引。解决方法是先删除索引再执行转换脚本,结果不用1小时就完成了,建立全部的索 引不到半个小时。原因就是第一种方式每次insert都改变索引顺序,共执行改变2000万次,而第二种方式整体上执行索引 顺序就一次。3. PLSQL程序性能问题分析方法本章主要介绍怎样找到出现性能问题PLSQL程序或语句的方法。31性能问题分析出现性能问题,我先要从整体进行分析,一般总体上会有几种现象: 整个系统运行速度都慢 在业务不忙的时候,所有模块都慢 只有在业务繁忙的时候,所有模块都慢 时快时慢 个别业务模块运行速度慢 在业务不忙的时候,该模块就慢 只有在业务繁忙的时候,该模块才慢 时快时慢一般导致系统性能慢的因素: 硬件:客户端、服务器CPU、内存和存储设备配置不符合应用系统要求 网络:网速低、丢包 操作系统参数设置:参数设置不合理 受到其他软件干扰:例如:防火墙、病毒 Weblogic设置:参数设置不合理 Oracle设置:内存、表空间、redolog、系统参数设置不合理等 PLSQL程序:plsql不优化、未使用索引、锁表在不同现象下,可能导致性能问题的因素:1. 一般来说,如果在不办理业务的情况下,整个系统性能就慢的话,应该和PLSQL程序优化是没 有关系的。可能的因素为硬件、网络、操作系统、其他软件干扰、ORACLE设置。2. 只有在业务繁忙的时候,整体系统性能都慢,有可能的因素有硬件、操作系统设置、 WEBLOGIC设置、ORACLE设置、PLSQL程序。如果在sqlplus下做查询都慢,那么就和 weblogic没有关系。3. 一般来说,如果在不办理业务的情况下,个别业务模块速度就慢的话,那么基本上就是PLSQL 程序不优化或未使用索引造成的。4. 只有在业务繁忙的时候,个别模块慢,有可能的因素有硬件、操作系统设置、WEBLOGIC设 置、ORACLE设置、PLSQL程序、锁表。这里我们重点是说明PLSQL优化、索引优化的问题,其他例如:硬件、网络、操作系统和oracle设置等 因素我们不进行说明。PLSQL优化、索引不使用的问题产生的影响:1. 对于某段不优化的程序或语句频繁或者全表扫描一个表时,它访问磁盘的时间和占用的吞吐量 是很高的,这就导致系统IO长时间处于忙的状态,导致整个系统性能下降。2. 对于某段不优化的程序或语句频繁或者全表扫描一个表时,其他的业务程序也访问同一个表 时,速度将大大下降。3. 如果是更新表操作时间长,还可能会导致锁等待,导致会话堵塞,weblogic端也出现压力问题,导致这个系统性能下降。我们一般根据这些现象、以及一些方法判断,来初步分析产生性能问题的大致原因的范围。不过对于这 一点,还是比较困难的,因为产生问题的原因是多种的,并且还有一定的关联。下面的章节介绍我们已 经断定是PLSQL优化、索引不使用的问题,我们通过什么方法来具体定位问题。3.2 Expain Plan分析索引使用在PL/SQL Developer等工具有一个Expain Plan分析的功能,这个功能可以帮助我们分析SQL语句是否使 用了索引、使用哪些索引和使用索引的效果。1. 选择 explain plan 的窗口2,在上面栏中输入SQL语句,然后点击工具栏上的EXECUTE执行(或按F8),就会在下面显示 Optmizergoal优化器的默认方式(也可手工选择),以及下面的解释计划,从解释计划上能看到哪个 条件语句使用了索引,哪个没有使用;哪个表使用了索引,使用了哪个索引,哪些表是全表扫描的 (TABLE ACCESS FULL)3.分析内容说明: COST:根据优化程序的基于开销的方法所估计出的操作开销值对于使用基于规则方法的语句该列为 空该列值没有特定的测量单位它只是一个用于比较执行规划开销大小的权重值 Cardinality:根据基于开销的方法对操作所访问行数的估计值 Bytes:根据基于开销的方法对操作所访问字节的估计 通过设置,我们还能看到更多的信息,例如:CPU使用、时间等等 全表扫描的(TABLE ACCESS FULL)肯定是速度慢的,如果是大数据量的表,那么这个语句是绝对影响性 能的。另外使用了索引也不一定性能就高,因为索引使用也有效率的情况,下面列出索引常见的使用类型:1. INDEX UNIQUE SCAN:唯一索引扫描,速度最快2. INDEXRANGE SCAN:范围索引扫描,使用这个索引时,就需要看COST、Cardinality、Bytes的大 小了,如果特别大,有时候还可能速度低于全表扫描的速度。我们在知道语句有问题,或者我们对语句进行优化时,这个工具是非常有用的。3.3 TOPSQL 分析程序有性能问题的时候,我们是不知道哪些语句存在性能的问题,尤其你不是开发人员。幸好有一些工 具可以帮助我们找到这些存在性能问题的语句。Toad工具和ORACLE9I的企业管理控制台工具可以捕获到这些问题语句(oracle10g中em的功能不够 好)。在TOAD和ORACLE9I工具中可以查询到TOPSQL顶级SQL的内容,通过CPU、IO吞吐量、占 用时间等信息的排序,我们可以找到最影响系统性能的语句,通过分析我们可以看到这些语句的解释计 划。根据解释计划,我们可以进行语句的优化,我们知道语句后,我们通过plsql的搜索功能就知道存在问题 语句的程序了。这个办法使用有个前提条件就是这些问题语句在系统上运行过,并且没有间隔过长的时间,因此最好是 在实际出现性能问题的ORACLE上不断的去监控,才能捕获到最全的问题语句。1. ORACLE9i企业管理控制台工具的topsql2.系统运行中的所有TOPSQL3.分析具体的SQL语句4.Sql分析的解释计划3.4针对性语句搜索TOPSQL分析也只能是找到未使用索引的语句(实际上这一点基本就足够解决性能的问题了),但是对 于2.4章节中的很多内容,没有办法进行捕获。我们可以采用针对性语句搜索,来尽量找到一些问题语句进行优化。在PLSQL工具中有一个Find DB Object的功能,可以进行搜索。我们可以搜索的关键特征信息: NOT IN UNION GROUPBY ORDER BY 、 Like % From tab、Update tab、delete tab,其中tab是数据量特别大的表,我们可以针对性的检查对大表访问 的语句(例如:ac20、ab09、kc22、kc24等)。这种办法很有局限性,不过也是一种检查代码的办法。3.5后台存储过程跟踪以上的各种办法,基本都不能检查出类似2.4.8和2.4.9等问题,当我们不能通过整体上去发现问题 的时候,我们对有性能问题程序直接进行后台的跟踪,有时候往往是最有效的。xjTest script | DBMS Output | Statistics | Profiler | Traceb * = MMy objectsAE:91_E:ACK AE:91_TSET AE:92 AB92H AB 93 AB93H AB 96 AEI96H AEI97 AEI97H AEI99 AEI99H AC01 AC01H AC02 AC02H AC04 AC04HItHitttHtttHlitHlitHlitH二-二三-三-三-IjiiiliiiiliitlliitlliitlliitlfHA三-三-三- -.:1-:.1-:.1-:.1-:.1-:.1-:.1-:.-:.-:.-:.-:.1-:.1-:.1-.:1-.:1-.:1-:.1-:.1-:1-:1-.begin- Cm21 the piccedurepk收熨理-P rc_a_位实收处理(p rm_主分配茴.甲采谯=a : p rm_主分配贽.用来源.,P上皿_征集通知:流水号=:p上皿_征集通知流水号 Km_到幅流,水号=:=-:prm_到幡流,水号, 町m_经办人= *也_经弭人.Km_分配类型=:=-:prni_-配矣型,Km_指定开始结食期=:=-:prm_指定开始结食期 Km_指定终止结耸期= :prm_指定癸止结食:期 町11_单位编号=:=:户皿_单校编号, prm_收主体= :prm_gk收主体, 即111_险:种串=:=-I户也_险种 聿f priii_lJ幅户标志=:=-:p111_旬|幅户标志/ priii_appcode =:=- : priii_appcode p riii_e r r orms g =:=- : p rm_e r r a rills gJ ;end;AC05HAC05LOGAC06Command Window - NewTest Window - Script for procedValue R F E E 17VariablePL主普配费用来源 咿_征集通知流水号 prm一到帐流水号匚叮1_经办人一rm分配类型TypeStringFloatFloatStringStrina
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸设计 > 毕设全套


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!