oracle性能优化建议

时间:2022-12-09 19:30:03


(1)连接查询的表顺序

在CBO模式下,当对多个表进行连接查询的时候,Oracle分析器会按照从右到左的顺序处理from字句中的表名

例如,下面会先查询dept

select a.empno,b.ename,c.dname
from emp_log a ,emp b,dept c

在执行时,Oracle会先查询dept表,根据dept表查询到行作为数据源串行连接emp表继续执行,因此dept表又称为基础表或者驱动 表。由于连接的顺序对查询的效率有非常大的影响,因此在处理多表连接时, 必须选择记录条数较少的表作为基础表。Oracle会使用排序或者合并的方式进行连接,比如先扫描dept表,然后对dept表进行排序,再扫描emp表,最后将所有检索出来的记录与第一个表的记录进行合并。

如果有三个以上的表连接查询,就需要选择交叉表作为基础表。交叉表是指那个被其他表所引用的表。由于emo_log是emp和dept表中的交叉表,既包含了dept表的内容又包含了emp的内容,因此上述查询可以将emp_log作为驱动表

select a.empno,b.ename,c.dname
from emp b,dept c,emp_log a 


(2)指定where的条件顺序

默认情况下,Oracle采用自下而上的顺序解析where字句,因此在处理多表查询的时候,表之间的连接必须写在其他的where条件之前,但是过滤数据记录的条件则必须写在where子句的尾部,以便在过滤了数据之后再进行连接处理,这样可以提升sql语句的性能。例

select a.empno ,a.ename,c.deptno,b.sal
from emp b,dept c,emp_log a 
where a.deptno=b.deptno
and c.deptno in (20,30)

(3)避免使用*符号

Oracle在遇到*符号的时候,会去查询数据字典中获取所有的列信息,然后依次转换成所有的列名,这将耗费较长的执行时间,因此要避免使用,尽量将所需的列信息逐个打出


(4)使用decode函数

灵活使用该函数可以减少很多对表的不必要的访问,详情见博文http://blog.csdn.net/sinat_32023305/article/details/78654446


(5)使用where而非having

where语句是在group by 语句之前筛选出记录,而having是在各种记录都筛选之后再进行过滤,也就是说having子句是在数据库中提取数据之后再筛选。因此尽量在筛选之前将数据使用where子句进行过滤,因此执行的顺序应该如下

1使用where子句查找符合条件的数据

2使用group by子句对数据进行分组

3在group by分组的基础上运行聚合函数计算每一组的值

4用having子句去掉不符合条件的组


(6)使用union而非or

如果要进行or运算的两个列都是索引列,可以考虑使用union来提升性能,但是必须保证这两个列都是索引列,否则执行的性能可能往往还不如or语句的性能

如果坚持使用or语句,需要记住尽量将返回记录最少的索引写在最前面,这样能获得较好的性能

另一个建议是在要对单个字段值进行or计算的时候,可以考虑使用in来代替。