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); |
注:下文中的错误和正确只是说明是否能正确使用索引,并不是说明语句正确与否,特此说明。
(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,'%');