高效SQL语句必杀技

发表于:2013-6-05 10:04

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:RobinsonCheng    来源:51Testing软件测试网采编

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - filter(LNNVL("OBJECT_ID"=69450))
   5 - access("OWNER"='SYSTEM')
         
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
         46  consistent gets
          0  physical reads
          0  redo size
      11383  bytes sent via SQL*Net to client
        712  bytes received via SQL*Net from client
         22  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
        301  rows processed

scott@CNMMBO> select * from t6
  2  where object_id=69450
  3  union
  4  select * from t6
  5  where owner='SYSTEM';

301 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 370530636
------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                |   301 |  7224 |     7  (72)| 00:00:01 |
|   1 |  SORT UNIQUE                  |                |   301 |  7224 |     7  (72)| 00:00:01 |
|   2 |   UNION-ALL                   |                |       |       |            |          |
|   3 |    TABLE ACCESS BY INDEX ROWID| T6             |     1 |    24 |     2   (0)| 00:00:01 |
|*  4 |     INDEX RANGE SCAN          | I_T6_OBJECT_ID |     1 |       |     1   (0)| 00:00:01 |
|   5 |    TABLE ACCESS BY INDEX ROWID| T6             |   300 |  7200 |     3   (0)| 00:00:01 |
|*  6 |     INDEX RANGE SCAN          | I_T6_OWNER     |   300 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   4 - access("OBJECT_ID"=69450)
   6 - access("OWNER"='SYSTEM')

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          7  consistent gets
          0  physical reads
          0  redo size
      11383  bytes sent via SQL*Net to client
        712  bytes received via SQL*Net from client
         22  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
        301  rows processed

  -->从上面的统计信息可知,consistent gets由46下降为7,故当where子句中谓词上存在索引时,使用union替换or更高效

  -->即使当列object_id与owner上不存在索引时,使用union仍然比or更高效(在Oracle 10g R2与Oracle 11g R2测试)

  4)避免索引列上使用函数

  -->下面是一个来自实际生产环境的例子

  -->表acc_pos_int_tbl上business_date列存在索引,由于使用了SUBSTR函数,此时索引失效,使用全表扫描

SELECT acc_num
     , curr_cd
     , DECODE( '20110728'
             , ( SELECT TO_CHAR( LAST_DAY( TO_DATE( '20110728', 'YYYYMMDD' ) ), 'YYYYMMDD' ) FROM dual ), 0
             ,   adj_credit_int_lv1_amt
               + adj_credit_int_lv2_amt
               - adj_debit_int_lv1_amt
               - adj_debit_int_lv2_amt )
          AS interest
FROM   acc_pos_int_tbl
WHERE  SUBSTR( business_date, 1, 6 ) = SUBSTR( '20110728', 1, 6 ) AND business_date <= '20110728';

  -->改进的办法

SELECT acc_num
     , curr_cd
     , DECODE( '20110728'
             , ( SELECT TO_CHAR( LAST_DAY( TO_DATE( '20110728', 'YYYYMMDD' ) ), 'YYYYMMDD' ) FROM dual ), 0
             ,   adj_credit_int_lv1_amt
               + adj_credit_int_lv2_amt
               - adj_debit_int_lv1_amt
               - adj_debit_int_lv2_amt )
          AS interest
FROM   acc_pos_int_tbl acc_pos_int_tbl
WHERE  business_date >= TO_CHAR( LAST_DAY( ADD_MONTHS( TO_DATE( '20110728', 'yyyymmdd' ), -1 ) )
                                + 1, 'yyyymmdd' )
       AND business_date <= '20110728';

  -->下面的例子虽然没有使用函数,但字符串连接同样导致索引失效

  -->低效:

SELECT account_name, amount
FROM   transaction
WHERE  account_name
       || account_type = 'AMEXA';

  -->高效:

SELECT account_name, amount
FROM   transaction
WHERE  account_name = 'AMEX' AND account_type = 'A';

《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号