Oracle语句优化30个规则详解(三)

2014-11-24 12:22:58 · 作者: · 浏览: 3
ion!=‘sydney’
and region!=‘perth’




   高效:

Sql代码
select region,avg(log_size)
from location
where region region!=‘sydney’
and region!=‘perth’
group by region




   15. 减少对表的查询
  在含有子查询的SQL语句中,要特别注意减少对表的查询。
  例如:
  低效

Sql代码
select tab_name
from tables
where tab_name=(selecttab_name
from tab_columns
where version=604)
and db_ver=(selectdb_ver
from tab_columns
where version=604)




   高效




 Update多个Column例子:

 低效:

Sql代码
UPDATEEMP
SETEMP_CAT=(SELECTMAX(CATEGORY)FROMEMP_CATEGORIES),
SAL_RANGE=(SELECTMAX(SAL_RANGE)FROMEMP_CATEGORIES)
WHEREEMP_DEPT=0020;

   高效:

Java代码

UPDATE EMP

SET(EMP_CAT,SAL_RANGE)

=(SELECT MAX(CATEGORY),MAX(SAL_RANGE)

FROM EMP_CATEGORIES)

WHERE EMP_DEPT=0020;

  16. 通过内部函数提高SQL效率。

   

Sql代码

SELECT H.EMPNO,E.ENAME,H.HIST_TYPE,T.TYPE_DESC,COUNT(*)

FROM HISTORY_TYPET,EMPE,EMP_HISTORYH

WHEREH.EMPNO=E.EMPNO

AND H.HIST_TYPE=T.HIST_TYPE

GROUP BY H.EMPNO,E.ENAME,H.HIST_TYPE,T.TYPE_DESC;

  通过调用下面的函数可以提高效率。

  

Sql代码

function lookup_hist_type(typin number) return varchar2

as

tdesc varchar2(30);

cursor c1 is

select type_desc

from history_type

where hist_type=typ;

begin

open c1;

fetch c1 into tdesc;

close c1;

return(nvl(tdesc,’ ’));

end;

function lookup_emp(empin number) return varchar2

as

ename varchar2(30);

cursor c1 is

selecte name

from emp

where empno=emp;

begin

open c1;

fetch c1 into ename;

close c1;

return(nvl(ename,’ ’));

end;

select h.empno,lookup_emp(h.empno),

h.hist_type,lookup_hist_type(h.hist_type),count(*)

from emp_historyh

group by h.empno,h.hist_type;

  (译者按: 经常在论坛中看到如 ‘能不能用一个SQL写出…。’ 的贴子, 殊不知复杂的SQL往往牺牲了执行效率。 能够掌握上面的运用函数解决问题的方法在实际工作中是非常有意义的)

17. 使用表的别名(Alias)

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

  (译者注: Column歧义指的是由于SQL中不同的表具有相同的Column名,当SQL语句中出现这个Column时,SQL解析器无法判断这个Column的归属)

  18. 用EXISTS替代IN

  在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率。

  低效:


Sql代码

select*

from emp(基础表)

where empno>0

and deptno in(select deptno

from dept

where loc=‘melb’)

  高效:


Sql代码

select *

from emp(基础表)

where empno>0

and exists(select‘x’

from dept

where dept.deptno=emp.deptno

and loc=‘melb’)

  (译者按: 相对来说,用NOT EXISTS替换NOT IN 将更显著地提高效率,下一节中将指出)

  19. 用NOT EXISTS替代NOT IN

  在子查询中,NOT IN子句将执行一个内部的排序和合并。 无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历)。 为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS.

  例如:


Sql代码

select *

from emp

where dept_nonotin(select dept_no

from dept

where dept_cat=’a’);

  为了提高效率。改写为:

  (方法一: 高效)


Sql代码

 select *

frome mpa,deptb

where a.dept_no=b.dept(+)

and b.dept_no is null

and b.dept_cat(+)=‘a’

(方法二: 最高效)


Sql代码

 select *

from empe

where not exists(select ‘x’

from deptd

where d.dept_no=e.dept_no

and dept_cat=‘a’);

  20. 用表连接替换EXISTS

  通常来说 , 采用表连接的方式比EXISTS更有效率


Sql代码

select ename

from empe

where exists(select ‘x’

from dept

where dept_no=e.dept_no

and dept_cat=‘a’);

  (更高效)


Sql代码

select ename

from deptd,empe

where e.dept_no=d.dept_no

and dept_cat=‘a’;

  (译者按: 在RBO的情况下,前者的执行路径包括FILTER,后者使用NESTED LOOP)

  21. 用EXISTS替换DISTINCT

  当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT. 一般可以考虑用EXIST替换

  例如:

  低效:


Sql代码