pl/sql优化小知识点

来源:互联网 发布:windows xp. 编辑:程序博客网 时间:2024/05/16 13:51

1.选择最有效的表名顺序

oracle的解析器按照从右到左的顺序处理from子句中的表名,因此写在from子句最后的表(基础表,drivingtable)将被最先处理。在from子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。

2.where子句中的连接顺序

oracle采用自下而上的顺序解析where子句,根据这个原理,表之间的连接必须写在其他where条件之前。

3.select子句中避免使用“*”

当你想在select子句中列出所有column时,使用动态sql列引用‘*’是一个方便的方法。不幸的是,这是一个非常低效的方法。实际上,oracle在解析的过程中,会将‘*’依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间。

4.用exists代替in

实际情况看,使用exists代替in效果不是很明显,基本一样。
在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行连接。在这种情况下,使用exists或(no exists)通常将提高查询的效率。

5.用表连接替换exists

在子查询的表和主表查询是多对一的情况,一般采用表连接的方式比exists更有效率。

6.用exists替换distinct

当提交一个包含一对多表信息的查询时,避免在select子句中使用distinct,一般可以考虑用exists替换。
exists使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果。因此如果不是特别研究和追求速度的话,查询一个表的数据需要关联其他表的这种情况查询,建议采用exists方式。

7.避免循环(游标)里面嵌查询

游标里面不能嵌入查询(或嵌入游标),其实也不能有update或delete语句,只能有insert语句。但在实际的编程情况下是不可能完全避免的,但我们一定要尽量避免。该类问题也是程序中出现过的问题,该类问题也可以大大提升程序效率,请大家一定注意。
优化的方法是尽量把游标循环中的查询语句放到游标查询中一起查询出来,这样相当于只访问了一次磁盘读到内存;如果放到游标中的话,假如游标有100万数据量,那么程序需要100万次磁盘,可以想象浪费了多少I/O的访问。
如果在程序编写上没有办法避免游标中有查询语句的话(一般情况是可以避免的),那么也要保证游标中的查询使用索引(即查询速度非常快),例如游标100万数据量,游标中的查询语句0.02秒,从这个速度来说是很快的,但总体上看100万*0.02秒=5小时33分钟,如果写一个不够优化的语句1秒,需要多次时间完成?

8.尽量使用union all 替换union

union会去掉重复的记录,会有排序的动作,会浪费时间。因此在没有重复记录的情况下或允许有重复记录的情况,要尽量采用union all来关联。

9.使用decode函数来减少处理时间

使用decode函数可以避免重复扫描相同记录或重复连接相同的表。

10.group by优化

group by 需要查询后排序,进度慢影响性能,如果查询数据量大,并且分组复杂,这样的查询语句在性能上是有问题的。

11.尽量避免使用order by 

order by需要查询后排序,速度慢影响性能,如果查询数据量大,排序的时间就很长。但我们也不能避免不使用,这样大家一定注意的一点是如果使用order by,那么排序的列表必须符合索引,这样在速度上会得到很大的提升。

12.用where子句替换having子句

避免使用having子句,having只会在检索所有记录之后才对结果集进行过滤。这个处理需要排序,总计等操作。如果能通过where子句限制记录的数目,那就能减少这方面的开销。

13.使用表别名

当在sql语句中连接多个表时,请使用表的别名并把别名前缀与每个column上。这样一来,就可以减少解析的时间并减少那些由column歧义引起的语法错误。

14.删除重复记录

一般数据转换的程序经常会用到该方法
最高效的删除重复记录的方法(因为使用了ROWID)
delete from ac01 a 
where a.rowid>(select min(b.rowid) from ac01 b where a.aac002=b.aac002 and a.aac003=b.aac003);

15.COMMIT使用

数据转换的程序需要注意这一点。
1.commit执行也是有时间的,不过时间特别短,但提交频率特别大必然也会浪费时间;
2.commit可以释放资源,在大量数据更新时,必须及时提交。
如果一条一提交,需要提交5000万必然浪费时间;如果整体提交,资源不能释放,性能必然下降。在实际编程时,应注意提交的次数和提交的数据量之间的平衡关系。

16.减少多表关联

表关联的越多,查询速度就越慢,尽量减少多个表的关联,建议表关联不要超过3个(子查询也属于表关联)。
数据转换上会存在大数据量表的关联,关联多了会影响索引的效率,可以采用建立临时表的方法,有时更能提高速度。

17.批量数据插入

数据转换时或大业务数据插入时,有以下几种办法进行数据插入(不包括imp,impdp和sqlloader)
1.Insert into ...select 方式
将查询的结果一次插入到目标表中
例如:insert into ac02 select * from ac01;
由于是一次查询一次插入,并且最后一次提交,它的速度要比下面描述的cursor的速度要快。但查询插入的数据量过大必然会占用更多的内存和undo表空间,只能在插入完成后提交,这样资源不能释放,会导致回滚表空间不足和快照过久的问题,另外一旦失败需要全部回滚。因此建议小数据量(例如:300万以下)的导入采用该种方式。
2.cursor方式
定义游标,然后逐行进行插入,然后定量提交。
3.批绑定的方式
通过游标查询将数据逐行写到数组里(实际上就是内存),然后通过批绑定的语句forall...insert into ..select ..into  values..,将内存的数据一次写到数据文件中。相比cursor的方式减少了对I/O的访问次数,提高了速度,但注意内存别溢出了。

18.索引使用优化

在实际的应用系统中索引问题导致性能问题可能占到百分之八十,在程序优化上索引问题是需要我们特别关注的。本段主要描述什么情况索引不生效。
1.避免在索引列上使用函数或运算
这个问题是在我们实际编程中出现过的,请大家一定注意。在索引列上使用函数或运算,查询条件都不会使用索引。
例如:
不使用索引
select * from ac01 where ka060='10001000' and to_char(aae030,'yyyymm')='200801';

使用索引
select * from ac01 where ka060='10001000' and aae030=to_date('200801','yyyymm');

不使用索引
select * from ac01 where ka060='10001000' and aae030+1=sysdate;

使用索引
select * from ac01 where ka060='10001000' and aae030=sysdate-1;

2.避免改变索引列的类型
索引列的条件如果类型不匹配,则不能使用索引
例如:
不使用索引
select * from ac01 where ka060=10001000;

使用索引
select * from ac01 where ka060='10001000';

3.避免在索引列上使用NOT
避免在索引列上使用NOT,NOT不会使查询条件使用索引。对于!=这样的判断也是不能使用索引的,索引只能告诉你什么存在于表中,而不能告诉你什么不存在于表中。
例如:
不使用索引(低效)
select * from ac01 where not ka060='10';

使用索引(高效)
select * from ac01 where ka060 in('20','30');

19.用>=替代>

虽然效果不是特别明显,但是建议采用这种方式
低效:
select * from ac01 where ka060>'10';

高效:
select * from ac01 where ka060>='20';
两者的区别在于,前者DBMS首先定位到ka060=‘10’的记录并且向前扫描到第一个ka060大于10的记录;而后者DBMS将直接跳到ka060='20'的记录。

20.避免在索引列上使用is null 和is not null

对于索引列使用is null或is not null不会使用该索引,因为空值不存在于索引列中,所以where子句中对索引列进行空值比较将oracle停用该索引。
例如:
低效(索引失效)
select * from ac01 where ka060 is not null;

高效(索引有效)
select * from ac01 where ka060 in('10','20','30');
在实际开发中,这样的问题很难避免,如果不是特别影响速度或要求速度的,可以忽略。

21.带通配符(%)的like语句

%在常量前面索引就不会使用

22.总是使用索引的第一个列

如果索引是建立在多个列上,只有在它的第一个列被where子句引用时,优化器才会选择使用该索引。
例如:
ac01的复合索引:ac011,ac012,ac013
select * from ac01 where ac012='01' and ac013='03';不会使用索引
select * from ac01 where ac011='01';使用索引
如果不使用索引第一列基本上不会使用索引,使用索引要按照索引的顺序使用,另外使用复合索引的列越多,查询的速度就越快。

 23.多个平等的索引

当sql语句的执行路径可以使用分布在多个表上的多个索引时,oracle会同时使用多个索引并在运行时对它们的记录进行合并,检索出仅对全部索引有效的记录。
在oracle选择执行路径时,唯一性索引的等级高于非唯一性索引,然而这个规则只有当where子句中索引列和常量比较才有效。如果索引列和其他表中的索引列相比较,这种子句在优化器中的等级是非常低的。
如果不同表中相同等级的索引被引用,from 子句中表的顺序将决定哪个会被率先使用。from子句中最后的表的索引将有最高的优先级。
如果同一个表中拥有相同等级的索引,oracle会分析最有效的索引去引用,其他的索引不会使用,如果这些相同等级的索引效果差不多,oracle可能会自动合并使用。

24.不明确的索引等级

当oracle无法判断索引的等级高低差别,优化器将只使用一个索引它就是where子句中列在最前面的。

25.自动选择索引

如果表中有两个及以上的索引,其中有一个是唯一性索引,其他是非唯一性。
在这种情况下,oracle将使用唯一性索引而完全忽略非唯一性索引。

26.一般导致系统性能慢的因素

1.硬件:客户端、服务器cpu、内存和存储设备配置不符合应用系统要求。
2.网络:网速低,丢包
3.操作系统参数配置:参数设置不合理
4.受到其他软件干扰:例如防火墙、病毒等。
5.weblogic设置:参数设置不合理
6.oracle设置:内存、表空间、redolog、系统参数设置不合理
PLSQL程序:plsql不优化、未使用索引、锁表
在不同现象下,可能导致性能问题的因素:
1.一般来说,如果在不办理业务的情况下,整个系统性能就慢的话,应该和PLSQL程序优化是没有关系的。可能的因素为硬件、网络、操作系统、其他软甲干扰、oracle设置。
2.只有在业务繁忙的时候,整个系统性能慢,有可能的因素为硬件、操作系统设置、weblogic设置、oracle设置、PLSQL程序、如果sqlplus做查询都慢,那么就和weblogic没有关系。
3.一般来说,如果不办理业务的情况下,个别业务模块就慢,那么基本上就是PLSQL程序不优化或未使用索引造成的。
4.只有在业务繁忙的时候,个别业务模块慢,有可能的因素有硬件、操作系统设置、weblogic设置、oracle设置、plsql程序、锁表。
这里我们重点说明PLSQL优化、索引优化。
PLSQL优化、索引不使用的问题产生的影响:
1.对于某段不优化的程序或语句频繁或者全表扫描一个表时,它访问磁盘的时间和占用的吞吐量是很大的,这就导致系统I/O长时间处于忙碌状态,导致整个系统性能下降。
2.对于某段不优化的程序或语句频繁或者全表扫描一个表时,其他的业务程序也访问同一个表时,速度将大大下降。
3.如果是更新表时间较长,还可能会导致锁等待,导致会话堵塞,weblogic端也出现压力问题,导致整个系统性能下降。
我们一般根据这些现象、以及一些方法判断,来初步分析产生性能问题的大致原因的范围。不过对于这一点,还是比较困难的,因为产生问题的原因是多种的,并且还有一定的关联。下面的章节介绍我们一定断定是PLSQL优化、不使用索引的问题,我们通过什么方法具体定位问题。
1.Expain plan分析索引使用
在PLSQLdeveloper等工具有一个Expain plan分析的功能,这个功能可以帮助我们分析sql语句是否使用了索引、使用哪些索引和使用索引的效果。
1.1选择expain plan窗口
1.2在上面栏中输入sql语句然后点击工具栏中的execute执行,就会在下面显示
optmizergoal优化器的默认方式(也可手工选择),以及下面的解释计划,从解释计划上可以看到哪个条件语句使用了索引,哪个没用,哪个表使用了索引,使用了哪个索引,哪些表是全表扫描的
1.3分析内容说明
cost:根据优化程序的基于开销的方法所估计出的操作开销值,对于使用基于规则方法的语句该列为空,该列值没有特定的测量单位,它只是一个用于比较执行计划开销大小的权重值
cardinality:根据基于开销的方法对操作所访问的行数的估计值
bytes:根据基于开销的方法对操作所访问字节的估计
通过设置,我们还可以看见更多的信息,如CPU使用、时间等等。
全表扫描的肯定是速度慢的,如果是大数据量的表,那么这个语句是绝对影响性能的。
另外使用了索引也不一定性能就高,因为索引使用也有效率高低的情况,下面列出索引常见的使用类型
1.index unique scan唯一索引扫描,速度最快
2.index range scan范围索引扫描,使用这个索引时,就需要看cost、cardinality,bytes的大小了,如果特别大,有时候还可能低于全表扫描的速度。
我们在知道语句有问题,或者我们队语句进行优化时,这个工具是非常有用的。
2.topsql分析
0 0