• 一次帮助网友优化的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' 这样的过滤省略了岂不是更好
  • 相关阅读:
    Xcode编译WebDriverAgentRunner报错:The bundle identifier for IntegrationApp.app couldn’t be read.解决方案
    python+django更新表结构执行相关命令报错:No installed app with label 'interface_crud'解决方案
    python激活虚拟环境env报错:no such file or directory: env/Scripts/activate解决方案
    Django创建api_crud app时报错:file "manage.py", line 16 ) from exc ^ SyntaxError: invalid syntax解决方案
    Redis未授权访问漏洞复现
    逻辑漏洞小结之SRC篇
    Linux下清空用户登录记录和命令历史的方法
    linux下直接清空日志的方法
    Linux Hackers/Suspicious Account Detection
    linux查看所有用户信息
  • 原文地址:https://www.cnblogs.com/hehe520/p/6330574.html
Copyright © 2020-2023  润新知