(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来代替。