高性能sql(摘自dw工作建议)

1)SQL尽量不用order by语句。尽量使用DataStore中sort方法。

(2)使用EXIST代替IN可能会提高性能,但并非所有情况都适用。具体要依据测试结果而定。

示例:

//一般情况下,效率较低。

select …

from emp

where empno> 0

and deptno in (select deptno  from dept

   whereloc = 'melb')

 

//一般情况下,效率较高。

select …

from emp

where empno> 0

and exists ( select 'x' from dept

 where dept.deptno = emp.deptno

and loc = 'melb')

(3)使用NOT EXIST或外连接代替NOT IN可能会提高性能,但并非所有情况都适用。具体要依据测试结果而定。

示例:

//一般情况下,效率较低。

select …

from emp

where dept_no not in ( select dept_no

                                   from dept

  where dept_cat = 'a');

 

//一般情况下,效率较高。

select …

from employee e, department d

where e.dept_no = d.dept_no(+)

and d.dept_no is null

and d.dept_cat(+) = 'a'

 

//一般情况下最高效。

select …

from employee e

where not exists ( select 'x'

 from department d

 where e.dept_no = d.dept_no)

(4)用多表连接代替EXISTS子句;一般情况下,使用表连接替代 EXIST 子句可提高性能。

示例:

//一般情况下,效率较低。

select ename

from employee e

where exists ( select 'x'

  from department d     

                      where dept_no = e.dept_no

  and dept_cat = 'a');

 

//一般情况下,效率较高。

select ename

from department d, employee e

where d.dept_no = e.dept_no

and d.dept_cat = 'a';

(5)少用DISTINCT,用EXISTS代替。一般情况下,使用 EXIST 子句替代 DISTINCT 子句可提高性能。

示例:

//一般情况下,效率较低。

select distinct d.dept_no, d.dept_name

from department d,employee e

where d.dept_no = e.dept_no

 

//一般情况下,效率较高。

select dept_no, dept_name

from department d

where exists ( select 'x'

                      from employee e

                      where e.dept_no = d.dept_no);

(6)使用ROWID提高检索速度。对SELECT得到的单行记录,需进行DELETE、UPDATE操作时,使用ROWID将会使效率大大提高。

(7)查询的WHERE过滤原则,应使过滤记录数最多的条件放在最前面。

(8)尽量使用共享的SQL语句。如经常使用select * from dept where deptno=值。如果每一个‘值’都是常量,则每一次都会重新解释,不能共享内存中的SQL语句优化结果。应把‘值’设置为一个变量,所有的共同语句都可以优化一次,高度共享语句解释优化的结果。

示例:select * from dept where deptno=:d;

该条规范对应我们的SQL中的绑定变量的使用;

(9)使用优化线索机制进行访问路径控制。

示例:

selecte.ename

from emp e

where e.job||''='CLERK';

//不如下面的语句好:

select /*+FULL(EMP)*/ e.ename

from emp e

where e.job='CLERK';

(10)建议SQL统一采用StringBuffer来拼串;

示例:

              sqlBF.append(" select jgbh,jgmc,parent,isValid,note ");

              sqlBF.append("from sysgroup ");

              sqlBF.append("  where jgbh like ? ");

sqlBF.append("    and jgmc like ? ");

(11)查询语句,要特别关注SQL查询出的数据量,当明确查询出的数据量比较大时,建议增加行数限制;

(12)减少对表的查询,在含有子查询的SQL语句中,要特别注意减少对表的查询。

示例:

//一般情况下,效率较低。

select tab_name

from tables

wheretab_name = (select tab_name

  fromtab_columns

  where version = 604)

anddb_ver = (select db_ver

 fromtab_columns

  where version = 604);

 

//一般情况下,效率较高。

selecttab_name

from tables

where (tab_name, db_ver) = (select tab_name, db_ver

  fromtab_columns

  where version = 604);

 

 

3.索引使用原则

注:下文中的错误和正确只是说明是否能正确使用索引,并不是说明语句正确与否,特此说明。

(1)尽量避免对索引列进行计算

           若对索引列进行了表达式计算,如加、减、乘、除等,索引会失效。

示例:

错误:where sal*1.1>950

正确:where sal>950/1.1

 

错误:where substr(name,1,7)=’CAPITAL’

正确:where name like ‘CAPITAL%’

(2)尽量注意比较值与索引列数据类型的一致性

当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换。严禁使用隐式的类型转换,必须显示的写出来。

示例:

emp_no为NUMBER型时

正确:where emp_no=123(推荐使用)

where emp_no=’123’(也可,不推荐使用)

 

emp_type为CHAR型时

错误:where emp_type=123 (此时,查询时,不利用索引列)

正确:where emp_type=’123’

(3)尽量避免使用NULL

避免在索引列上使用IS NULL和IS NOT NULL,将用不到索引。

示例:

错误:where comm IS NOT NULL

错误:where comm IS NULL

正确:where comm>=0

(4)尽量避免使用NOT=(!=)

“!=”和“<>”因为自动加了NOT运算符,将不使用索引,避免使用。

示例:

错误:where deptno!=0

正确:where deptno>0

(5)对于复合索引,SQL语句必须使用主索引列

如果索引是建立在多个列上,只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引。

示例:

复合索引(deptno,job)

正确:where deptno=20 and job=’MANAGER’

正确:where deptno=20

正确:where job=’MANAGER’ and deptno=20

错误:where job=’MANAGER’

(6)ORDER BY子句

子句中,列的顺序与索引列的顺序一致;

子句中,列应为非空列。

(7)查询列与索引列次序(WHERE)的一致性

示例:

selectempno,job

fromemp

whereempno<100

and job=’MANAGER’;

(8)避免索引列条件由通配符(%)开始

           索引列由通配符(%)开始时,索引失效。

示例:

where manager like ‘%HANMAN' 将进行全表扫描。

(9)避免相同的索引列互相比较

相同的索引列不能互相比较,这将会启用全表扫描。

示例:

where account_name = nvl(:acc_name,account_name);

建议改写为:

where account_name like nvl(:acc_name,'%');

你可能感兴趣的:(高性能sql(摘自dw工作建议))