一次帮助网友优化的SQL案例

网友QQ发来如下信息,问我下面这个SQL是否能有性能提升的地方,他们监控到这个SQL磁盘读很高
SQL> set autotrace on
SQL> select * from( select GRDL_ID qyid,KHMC nsrmc,KHBM nsrsbh,KHBM six_nsrsbh,'' six_dssh,gjc,fzgs_dm,'2' khlx from khgl_grdlxx
  2      union all
  3        select dwkh_id qyid, khmc nsrmc,nvl(nsrsbh,dssh) nsrsbh,nvl(six_nsrsbh,six_dssh) six_nsrsbh,six_dssh,gjc,fzgs_dm,'0' khlx from KHGL_DWKH_COREINFO
  4      union all
  5        select DLS_BM qyid,DLS_MC nsrmc,DLS_BM nsrsbh,DLS_BM six_nsrsbh,'' six_dssh,gjc,fzgs_dm,'1' khlx from KHGL_DLSJBXX
  6     )
  7      where (six_nsrsbh = '706773' or six_dssh = '706773')  and rownum<11;

QYID                             NSRMC
-------------------------------- -------------------------------------------------------------------------------------
a4af925f2a224bc4a8ac42dc87bb5192 农一师塔里木广告信息公司
b59f82aa67ae4b88b331a4042e1ced43 保定市丽景园林绿化有限公司
6db2f2cc8d8446a2b80f190fffd1ff72 保定市绿景园林绿化有限公司


执行计划
----------------------------------------------------------
Plan hash value: 112825667

-------------------------------------------------------------------------------------------
| Id  | Operation            | Name               | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                    |    10 |  1320 |    18   (0)| 00:00:01 |
|*  1 |  COUNT STOPKEY       |                    |       |       |            |          |
|   2 |   VIEW               |                    |    32 |  4224 |    18   (0)| 00:00:01 |
|   3 |    UNION-ALL         |                    |       |       |            |          |
|*  4 |     TABLE ACCESS FULL| KHGL_GRDLXX        |    11 |   803 |     5   (0)| 00:00:01 |
|*  5 |     TABLE ACCESS FULL| KHGL_DWKH_COREINFO |    11 |  1144 |     7   (0)| 00:00:01 |
|*  6 |     TABLE ACCESS FULL| KHGL_DLSJBXX       |    10 |   380 |     6   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------

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

   1 - filter(ROWNUM<11)
   4 - filter(''='706773' OR "KHBM"='706773')
   5 - filter(NVL("SIX_NSRSBH","SIX_DSSH")='706773' OR "SIX_DSSH"='706773')
   6 - filter(''='706773' OR "DLS_BM"='706773')


统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      27226  consistent gets
      26937  physical reads
          0  redo size
       1288  bytes sent via SQL*Net to client
        469  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          3  rows processed
根据SQL的执行计划和统计信息可以看出,这个SQL效率确非常低下,3个表都采用了全表扫描,这个必然导致物理读高。
仔细分析执行计划以及SQL语句,我真的无语了,这个SQL语句写得之烂让我情何以堪,于是我做如下改写
select *
  from (select GRDL_ID qyid,
               KHMC nsrmc,
               KHBM nsrsbh,
               KHBM six_nsrsbh,
               '' six_dssh,
               gjc,
               fzgs_dm,
               '2' khlx
          from khgl_grdlxx
         where KHBM = '706773'
        union all
        select dwkh_id qyid,
               khmc nsrmc,
               nvl(nsrsbh, dssh) nsrsbh,
               nvl(six_nsrsbh, six_dssh) six_nsrsbh,
               six_dssh,
               gjc,
               fzgs_dm,
               '0' khlx
          from KHGL_DWKH_COREINFO where (six_nsrsbh = '706773' or
                                  six_dssh = '706773')
        union all
        select DLS_BM qyid,
               DLS_MC nsrmc,
               DLS_BM nsrsbh,
               DLS_BM six_nsrsbh,
               '' six_dssh,
               gjc,
               fzgs_dm,
               '1' khlx
          from KHGL_DLSJBXX
         where DLS_BM = '706773')
 where  rownum < 11;

改写之后,SQL执行计划如下:
执行计划
----------------------------------------------------------
Plan hash value: 1863808260

----------------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name                   | Rows  | Bytes | Cost (%CPU)| Time
----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                        |     8 |  1056 |    12   (0)| 00:00:
|*  1 |  COUNT STOPKEY                      |                        |       |       |            |
|   2 |   VIEW                              |                        |     8 |  1056 |    12   (0)| 00:00:
|   3 |    UNION-ALL                        |                        |       |       |            |
|   4 |     TABLE ACCESS BY INDEX ROWID     | KHGL_GRDLXX            |     1 |    73 |     2   (0)| 00:00:
|*  5 |      INDEX UNIQUE SCAN              | IDX_GRDLXX_KHBM        |     1 |       |     1   (0)| 00:00:
|   6 |     TABLE ACCESS BY INDEX ROWID     | KHGL_DWKH_COREINFO     |     6 |   624 |     8   (0)| 00:00:
|   7 |      BITMAP CONVERSION TO ROWIDS    |                        |       |       |            |
|   8 |       BITMAP OR                     |                        |       |       |            |
|   9 |        BITMAP CONVERSION FROM ROWIDS|                        |       |       |            |
|* 10 |         INDEX RANGE SCAN            | IDX_DWKHCORE_SIX_DSSH  |       |       |     3   (0)| 00:00:
|  11 |        BITMAP CONVERSION FROM ROWIDS|                        |       |       |            |
|* 12 |         INDEX RANGE SCAN            | IDX_DWKHCORE_SIXNSRSBH |       |       |     3   (0)| 00:00:
|  13 |     TABLE ACCESS BY INDEX ROWID     | KHGL_DLSJBXX           |     1 |    38 |     2   (0)| 00:00:
|* 14 |      INDEX UNIQUE SCAN              | PK_KHGL_DLSJBXX        |     1 |       |     1   (0)| 00:00:
----------------------------------------------------------------------------------------------------------

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

   1 - filter(ROWNUM<11)
   5 - access("KHBM"='706773')
  10 - access("SIX_DSSH"='706773')
  12 - access("SIX_NSRSBH"='706773')
  14 - access("DLS_BM"='706773')


统计信息
----------------------------------------------------------
         15  recursive calls
          0  db block gets
         17  consistent gets
          0  physical reads
          0  redo size
       1288  bytes sent via SQL*Net to client
        469  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          3  rows processed

为什么要这么改写呢? 因为不改写的执行计划里面有''='706773' 这个会限制使用索引
其实这里ORACLE用到的CBO转换技术有1个,叫做Pushing Predicate(谓词推入),但是在第一个SQL语句中,由于有这样的SELECT 条件'' six_dssh
导致谓词推入的时候过滤也成了''='706773' ,从这里也知道CBO还是不够智能,如果能智能一点,帮我们把''='706773' 这样的过滤省略了岂不是更好

你可能感兴趣的:(sql,优化,filter,table,Access,disk)