1. WHERE子句中的连接顺序
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。
如:
Select …
From operation_detail t, cargo_request r
Where t.request_sysid = r.request_sysid
And to_char(t.ingate_time,’YYYYMMDD’) >= ’20090101’
And to_char(t.ingate_time,’YYYYMMDD’) < ’20100101’
And request_sysid = 20090904001
2. 用EXISTS替代IN,NOT EXISTS替代NOT IN
Select …
From operation_detail
Where request_sysid,auto_no)
In (select request_sysid,auto_no from auto_trust_info where request_sysid = 20090904001)
改成:
Select …
From operation_detail d
Where exists (select 1 from auto_trust_info t where t.request_sysid = d.request_sysid
And t.auto_no = d.auto_no
And t.request_sysid= 20090904001)
3. 用INSTR替代LIKE
Select … from operation_detail whereinstr(auto_no , ’浙B’) > 0
4. 用EXISTS替换DISTINCT当提交一个包含一对多表信息的查询时,避免在SELECT子句中使用DISTINCT. 一般可以考虑用EXIST替换
低效:
select distinct r.request_sysid from cargo_request r,plan_auto_connection p
Where r.request_sysid = p.request_sysid
And p.end_flag = ’N’
高效:
select r.request_sysid from cargo_request r
where exists (select 1 from plan_auto_connection p
where r.request_sysid = p.request_sysid
and p.end_flag = ’N’)
EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果。
5. 用WHERE替代HAVING
select … from test group by no having no>=9001
改为
select … from test where having no>=9001 group by no
6. 减少对表的查询
低效
select tab_name
from tables
where tab_name = ( select tab_name
from tab_columns
where version = 604)
and db_ver= ( select db_ver
from tab_columns
Where version = 604)
高效
Select tab_name
From tables
Where (tab_name,db_ver) = (select tab_name,db_ver)
From tab_columns
Where version = 604)
7. 使用DECODE函数来减少处理时间
使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表。
8.在查询条件中不要对索引条件使用函数,而是在常量上使用,
如:
Query 1: Select C1, C2, …… Cn
From tb_A
Where handoff_date = to_date(‘2004-01-01’,’yyyy-mm-dd’)
Query 2: Select C1, C2, …… Cn
From tb_A
Where to_char(handoff_date,’yyyy-mm-dd’) = ‘2004-01-01’
1的效率比明显地比2好...
9. 避免在索引列上使用not、 使用计算
在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的影响.当ORACLE”碰到”NOT,他就会停止使用索引转而执行全表扫描.在索引列上使用计算,WHERE子句中,假如索引列是函数的一部分.优化器将不使用索引而使用全表扫描.
举例:
低效:
SELECT … FROM DEPT WHERE SAL * 12 > 25000;
高效:
SELECT … FROM DEPT WHERE SAL > 25000/12;
10. 避免在索引中使用任何可以为空的列,ORACLE将无法使用该索引.
对于单列索引,假如列包含空值,索引中将不存在此记录.对于复合索引,假如每个列都为空,索引中同样不存在此记录. 假如至少有一个列不为空,则记录存在于索引中.举例:假如唯一性索引建立在表的A列和B列上,并且表中存在一条记录的A,B值为(123,null) , ORACLE将不接受下一条具有相同A,B值(123,null)的记录(插入).然而假如所有的索引列都为空,ORACLE将认为整个键值为空而空不等于空.因此你可以插入1000条具有相同键值的记录,当然它们都是空!因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引.低效: (索引失效)SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;
高效: (索引有效) SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;
11. 外连接 (+) 修改成 left join on形式
(+)的外连接是属于sql92标准left join on是sql99标准,left join on不仅表的连接结构上更清晰了,而且在取字段不会进行全表扫描,例如
SELECT * FROM table1,table2 , table3
Where table1.field1 = table2.field2(+)
And table1.field1 = table3.field3(+);修改成:SELECT *
FROM (table1 LEFT JOIN table3 ON table1.field1 = table3.field3) LEFT JOIN table2 ON table3.field3 = table2.field2;