日期:2014-05-16  浏览次数:20468 次

关于数据库性能优化方面的一些总结之三

(21) 避免在索引列上使用NOT 通常, 
我们要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的影响. 当ORACLE”遇到”NOT,他就会停止使用索引转而执行全表扫描.
(22) 避免在索引列上使用计算.
WHERE子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描.?
举例:?
低效:?

SELECT … FROM  DEPT  WHERE SAL * 12 > 25000; 

?
高效:?

SELECT … FROM DEPT WHERE SAL > 25000/12;

?
(23) 用>=替代>
高效:?

SELECT * FROM  EMP  WHERE  DEPTNO >=4 

?
低效:?

SELECT * FROM EMP WHERE DEPTNO >3 

?
两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录.
(24) 用UNION替换OR (适用于索引列)
通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. 注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低. 在下面的例子中, LOC_ID 和REGION上都建有索引.?
高效:?

SELECT LOC_ID , LOC_DESC , REGION 
FROM LOCATION 
WHERE LOC_ID = 10 
UNION 
SELECT LOC_ID , LOC_DESC , REGION 
FROM LOCATION 
WHERE REGION = “MELBOURNE” 

?
低效:?

SELECT LOC_ID , LOC_DESC , REGION 
FROM LOCATION 
WHERE LOC_ID = 10 OR REGION = “MELBOURNE” 

?
如果你坚持要用OR, 那就需要返回记录最少的索引列写在最前面.
(25) 用IN来替换OR??
这是一条简单易记的规则,但是实际的执行效果还须检验,在ORACLE8i下,两者的执行路径似乎是相同的. 
低效:?

SELECT…. FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30;

?
高效?

SELECT… FROM LOCATION WHERE LOC_IN  IN (10,20,30);

?
(26) 避免在索引列上使用IS NULL和IS NOT NULL
避免在索引中使用任何可以为空的列,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