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';
[if !vml]
[endif](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)尽量避免对索引列进行计算
若对索引列进行了表达式计算,如加、减、乘、除等,索引会失效。
示例:
错误:wheresal*1.1>950
正确:wheresal>950/1.1
错误:wheresubstr(name,1,7)=’CAPITAL’
正确:wherename like ‘CAPITAL%’
(2)尽量注意比较值与索引列数据类型的一致性
当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换。严禁使用隐式的类型转换,必须显示的写出来。
示例:
emp_no为NUMBER型时
正确:where
emp_no=123(推荐使用)
where
emp_no=’123’(也可,不推荐使用)
emp_type为CHAR型时
错误:where
emp_type=123 (此时,查询时,不利用索引列)
正确:whereemp_type=’123’
(3)尽量避免使用NULL
避免在索引列上使用IS NULL和IS NOT NULL,将用不到索引。
示例:
错误:wherecomm IS NOT NULL
错误:wherecomm IS NULL
正确:wherecomm>=0
(4)尽量避免使用NOT=(!=)
“!=”和“<>”因为自动加了NOT运算符,将不使用索引,避免使用。
示例:
错误:wheredeptno!=0
正确:wheredeptno>0
(5)对于复合索引,SQL语句必须使用主索引列
如果索引是建立在多个列上,只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引。
示例:
复合索引(deptno,job)
正确:wheredeptno=20 and job=’MANAGER’
正确:wheredeptno=20
正确:wherejob=’MANAGER’ and deptno=20
错误:wherejob=’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,'%');