zoukankan      html  css  js  c++  java
  • ORACLE SQL性能优化系列 (十一)

    36.       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, 那就需要返回记录最少的索引列写在最前面.

     

    注意:

     

    WHERE KEY1 = 10   (返回最少记录)

    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 NULLIS 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;

  • 相关阅读:
    搜索引擎代码资源
    shell十三问(很不错的shell解释)
    Export/Import 使用技巧与常见错误
    利用java实现数据结构中常用的插入排序和快速排序算法
    java23种设计模式与追MM
    sqlldr使用小结(zt)
    排序算法的java实现的网址链接
    Rdesktop与Window相联
    java抽取word,pdf的四种武器
    常用数据库JDBC连接写法
  • 原文地址:https://www.cnblogs.com/HondaHsu/p/1345399.html
Copyright © 2011-2022 走看看