当前位置:首页 > Oracle+performance
OR KEY2 = 20 (返回最多记录) ORACLE 内部将以上转换为
WHERE KEY1 = 10 AND((NOT KEY1 = 10) AND KEY2 = 20) 译者按:
下面的测试数据仅供参考: (a = 1003 返回一条记录 , b = 1 返回1003条记录) SQL> select * from unionvsor /*1st test*/ 2 where a = 1003 or b = 1; 1003 rows selected. Execution Plan
---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE 1 0 CONCATENATION
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'UNIONVSOR' 3 2 INDEX (RANGE SCAN) OF 'UB' (NON-UNIQUE) 4 1 TABLE ACCESS (BY INDEX ROWID) OF 'UNIONVSOR' 5 4 INDEX (RANGE SCAN) OF 'UA' (NON-UNIQUE) Statistics
---------------------------------------------------------- 0 recursive calls 0 db block gets 144 consistent gets 0 physical reads 0 redo size
63749 bytes sent via SQL*Net to client 7751 bytes received via SQL*Net from client 68 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1003 rows processed
SQL> select * from unionvsor /*2nd test*/ 2 where b = 1 or a = 1003 ; 1003 rows selected. Execution Plan
---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE 1 0 CONCATENATION
2 1 TABLE ACCESS (BY INDEX ROWID) OF 'UNIONVSOR' 3 2 INDEX (RANGE SCAN) OF 'UA' (NON-UNIQUE) 4 1 TABLE ACCESS (BY INDEX ROWID) OF 'UNIONVSOR' 5 4 INDEX (RANGE SCAN) OF 'UB' (NON-UNIQUE) Statistics
---------------------------------------------------------- 0 recursive calls 0 db block gets
143 consistent gets 0 physical reads 0 redo size
63749 bytes sent via SQL*Net to client 7751 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1003 rows processed
SQL> select * from unionvsor /*3rd test*/ 2 where a = 1003 3 union
4 select * from unionvsor 5 where b = 1;
1003 rows selected. Execution Plan
---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE 1 0 SORT (UNIQUE) 2 1 UNION-ALL
3 2 TABLE ACCESS (BY INDEX ROWID) OF 'UNIONVSOR' 4 3 INDEX (RANGE SCAN) OF 'UA' (NON-UNIQUE) 5 2 TABLE ACCESS (BY INDEX ROWID) OF 'UNIONVSOR' 6 5 INDEX (RANGE SCAN) OF 'UB' (NON-UNIQUE) Statistics
---------------------------------------------------------- 0 recursive calls 0 db block gets 10 consistent gets 0 physical reads 0 redo size
63735 bytes sent via SQL*Net to client 7751 bytes received via SQL*Net from client
68 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 1003 rows processed
用UNION的效果可以从consistent gets和 SQL*NET的数据交换量的减少看出 37. 用IN来替换OR
下面的查询可以被更有效率的语句替换: 低效: 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);
译者按:这是一条简单易记的规则,但是实际的执行效果还须检验,在ORACLE8i下,两者的执行路径似乎是相同的。
38. 避免在索引列上使用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_CODE >=0; 39. 总是使用索引的第一个列
如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引。
译者按:这也是一条简单而重要的规则。 见以下实例。
SQL> create table multiindexusage ( inda number , indb number , descr varchar2(10)); Table created.
SQL> create index multindex on multiindexusage(inda,indb); Index created.
SQL> set autotrace traceonly
SQL> select * from multiindexusage where inda = 1; Execution Plan
---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'MULTIINDEXUSAGE' 2 1 INDEX (RANGE SCAN) OF 'MULTINDEX' (NON-UNIQUE) SQL> select * from multiindexusage where indb = 1; Execution Plan
---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'MULTIINDEXUSAGE'
很明显, 当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引 40. ORACLE内部操作
当执行查询时,ORACLE采用了内部的操作。 下表显示了几种重要的内部操作。
ORACLE Clause ORDER BY UNION MINUS INTERSECT DISTINCT,MINUS,INTERSECT,UNION MIN,MAX,COUNT GROUP BY ROWNUM Queries involving Joins CONNECT BY
内部操作 SORT ORDER BY UNION-ALL MINUS INTERSECT SORT UNIQUE SORT AGGREGATE SORT GROUP BY COUNT or COUNT STOPKEY SORT JOIN,MERGE JOIN,NESTED LOOPS CONNECT BY 41. 用UNION-ALL 替换UNION ( 如果有可能的话)
当SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序。
如果用UNION ALL替代UNION, 这样排序就不是必要了。 效率就会因此得到提高。 举例: 低效:
SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = ‘31-DEC-95’ UNION
SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = ‘31-DEC-95’ 高效:
SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = ‘31-DEC-95’ UNION ALL
SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = ‘31-DEC-95’
译者按:需要注意的是,UNION ALL 将重复输出两个结果集合中相同记录。 因此各位还是要从业务需求分析使用UNION ALL的可行性。
UNION 将对结果集合排序,这个操作会使用到SORT_AREA_SIZE这块内存。 对于这块内存的优化也是相当重要的。 下面的SQL可以用来查询排序的消耗量 Select substr(name,1,25) \, substr(value,1,15) \ from v$sysstat where name like 'sort%'
共分享92篇相关文档