ORACLE SQL性能优化系列 (十)

2/9/2008来源:Oracle教程人气:4571

Oracle SQL性能优化系列 (十) 
31. 强制索引失效     假如两个或以上索引具有相同的等级,你可以强制命令ORACLE优化器使用其中的一个(通过它,检索出的记录数量少) .   举例:   SELECT ENAME FROM EMP WHERE EMPNO = 7935 AND DEPTNO + 0 = 10 /*DEPTNO上的索引将失效*/ AND EMP_TYPE ‘’ = ‘A’ /*EMP_TYPE上的索引将失效*/   这是一种相当直接的提高查询效率的办法. 但是你必须谨慎考虑这种策略,一般来说,只有在你希望单独优化几个SQL时才能采用它.   这里有一个例子关于何时采用这种策略,   假设在EMP表的EMP_TYPE列上有一个非唯一性的索引而EMP_CLASS上没有索引.   SELECT ENAME FROM EMP WHERE EMP_TYPE = ‘A’ AND EMP_CLASS = ‘X’;   优化器会注重到EMP_TYPE上的索引并使用它. 这是目前唯一的选择. 假如,一段时间以后, 另一个非唯一性建立在EMP_CLASS上,优化器必须对两个索引进行选择,在通常情况下,优化器将使用两个索引并在他们的结果集合上执行排序及合并. 然而,假如其中一个索引(EMP_TYPE)接近于唯一性而另一个索引(EMP_CLASS)上有几千个重复的值. 排序及合并就会成为一种不必要的负担. 在这种情况下,你希望使优化器屏蔽掉EMP_CLASS索引. 用下面的方案就可以解决问题. SELECT ENAME FROM EMP WHERE EMP_TYPE = ‘A’ AND EMP_CLASS’’ = ‘X’;   32. 避免在索引列上使用计算. WHERE子句中,假如索引列是函数的一部分.优化器将不使用索引而使用全表扫描.   举例:   低效: SELECT … FROM DEPT WHERE SAL * 12 > 25000;   高效: SELECT … FROM DEPT WHERE SAL > 25000/12;   译者按: 这是一个非常实用的规则,请务必牢记   33. 自动选择索引 假如表中有两个以上(包括两个)索引,其中有一个唯一性索引,而其他是非唯一性. 在这种情况下,ORACLE将使用唯一性索引而完全忽略非唯一性索引.   举例: SELECT ENAME FROM EMP WHERE EMPNO = 2326 AND DEPTNO = 20 ;   这里,只有EMPNO上的索引是唯一性的,所以EMPNO索引将用来检索记录. TABLE access BY ROWID ON EMP INDEX UNIQUE SCAN ON EMP_NO_IDX   34. 避免在索引列上使用NOT 通常, 我们要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的 影响. 当ORACLE”碰到”NOT,他就会停止使用索引转而执行全表扫描. 举例:   低效: (这里,不使用索引)   SELECT … FROM DEPT WHERE DEPT_CODE NOT = 0;   高效: (这里,使用了索引)   SELECT … FROM DEPT WHERE DEPT_CODE > 0;   需要注重的是,在某些时候, ORACLE优化器会自动将NOT转化成相对应的关系操作符. NOT > to <= NOT >= to < NOT < to >= NOT <= to >     译者按: 在这个例子中,作者犯了一些错误. 例子中的低效率SQL是不能被执行的. 我做了一些测试:   SQL> select * from emp where NOT empno > 1; no rows selected Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' 2 1 INDEX (RANGE SCAN) OF 'EMPNO' (UNIQUE)   SQL> select * from emp where empno <= 1; no rows selected Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE 1 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP' 2 1 INDEX (RANGE SCAN) OF 'EMPNO' (UNIQUE)   两者的效率完全一样,也许这符合作者关于” 在某些时候, ORACLE优化器会自动将NOT转化成相对应的关系操作符” 的观点.   35. 用>=替代>   假如DEPTNO上有一个索引,   高效:   SELECT * FROM EMP WHERE DEPTNO >=4   低效:   SELECT * FROM EMP WHERE DEPTNO >3   两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录.