• 又是latch: cache buffers chains惹得祸


    前言

    一大早,客户给我打电话说:

    xx,应用很慢,查询数据总是超时,让我看看。。。

    根据多年DBA经验,首当其冲的肯定是去查询数据库在这段时间都在干嘛。

    分析

    导出awr报告分析

    1). 数据库在此时间段非常繁忙。
    这里写图片描述
    2). 查看Top 5 Timed Events,出现了Concurrency等待事件latch: library cache**
    这里写图片描述
    3). 查看SQL ordered by Gets,不看不知道,一看吓一跳
    这里写图片描述
    4). *50pwxa3bzp7gkSQL语句

    select *
      from (select d.*, rownum as num
              from (SELECT A.BILLNO,
                           A.BILLCODE,
                           A.GETDATE,
                           A.GETUNITCODE,
                           A.GETCODE,
                           A.GETORGANCODE,
                           A.USEORGANCODE,
                           A.USEDATE,
                           A.USEUNITCODE,
                           A.USERCODE,
                           A.CURRENCYCODE,
                           A.AMOUNT,
                           A.NAME,
                           A.NOTES,
                           A.STATUSCODE,
                           A.IFPAGEONHOLE,
                           A.OPCODE,
                           A.OPUNITCODE,
                           A.OPDATE,
                           A.LOCKTIME,
                           A.GETAGENTCODE,
                           (SELECT D.AGENTNAME
                              FROM SYN_MM_AGENTCODE_TC D
                             WHERE D.AGENTCODE = A.GETAGENTCODE) AS GETAGENTNAME,
                           A.USEAGENTCODE,
                           A.OUTSTATUS,
                           CASE A.BILLCODE
                             WHEN 'B2010005' THEN
                              A.FACTBILLCODE
                             ELSE
                              ''
                           END FACTBILLCODE,
                           A.SALES,
                           A.FROMDATE,
                           A.TODATE,
                           (SELECT BILLNAME
                              FROM BD_BILLCODE
                             WHERE BILLCODE = A.BILLCODE) BILLNAME,
                           (SELECT HANDLERNAME
                              FROM BD_HANDLER
                             WHERE HANDLERCODE = A.USERCODE) USERNAME,
                           (SELECT HANDLERNAME
                              FROM BD_HANDLER
                             WHERE HANDLERCODE = A.GETCODE) GETERNAME,
                           (SELECT NO3
                              FROM B_BILLDETAIL
                             WHERE BILLNO = A.BILLNO
                               AND BILLCODE = A.BILLCODE
                               AND FACTBILLCODE = A.FACTBILLCODE) ONLINEINVOICENO,
                           (SELECT NO4
                              FROM B_BILLDETAIL
                             WHERE BILLNO = A.BILLNO
                               AND BILLCODE = A.BILLCODE
                               AND FACTBILLCODE = A.FACTBILLCODE) ONLINEINVOICECODE
                      FROM B_BILL A
                     WHERE 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                       AND TRIM(BILLNO) >= :B1
                       AND TRIM(BILLNO) <= :B2
                       AND 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                     ORDER BY A.BILLNO) d
             where rownum <= 1)
     where num > 0
    
    执行计划:
     Plan hash value: 4085294641
    
    ------------------------------------------------------------------------------------------------------
    | Id  | Operation                      | Name                | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT               |                     |     1 |  4632 |     9   (0)| 00:00:01 |
    |*  1 |  TABLE ACCESS FULL             | CHAGENTBASE         |     1 |    56 |     6   (0)| 00:00:01 |
    |   2 |  TABLE ACCESS BY INDEX ROWID   | BD_BILLCODE         |     1 |    31 |     1   (0)| 00:00:01 |
    |*  3 |   INDEX UNIQUE SCAN            | PK_BD_BILLCODE      |     1 |       |     0   (0)| 00:00:01 |
    |   4 |  TABLE ACCESS BY INDEX ROWID   | T_EMPLOYEE_VIEW     |     1 |    26 |     2   (0)| 00:00:01 |
    |*  5 |   INDEX RANGE SCAN             | IND_T_EMPLOYEE_VIEW |     1 |       |     1   (0)| 00:00:01 |
    |   6 |  TABLE ACCESS BY INDEX ROWID   | T_EMPLOYEE_VIEW     |     1 |    26 |     2   (0)| 00:00:01 |
    |*  7 |   INDEX RANGE SCAN             | IND_T_EMPLOYEE_VIEW |     1 |       |     1   (0)| 00:00:01 |
    |   8 |  TABLE ACCESS BY INDEX ROWID   | B_BILLDETAIL        |     1 |    50 |     4   (0)| 00:00:01 |
    |*  9 |   INDEX RANGE SCAN             | PK_B_BILLDETAIL_02  |     1 |       |     3   (0)| 00:00:01 |
    |  10 |  TABLE ACCESS BY INDEX ROWID   | B_BILLDETAIL        |     1 |    50 |     4   (0)| 00:00:01 |
    |* 11 |   INDEX RANGE SCAN             | PK_B_BILLDETAIL_02  |     1 |       |     3   (0)| 00:00:01 |
    |* 12 |  VIEW                          |                     |     1 |  4632 |     9   (0)| 00:00:01 |
    |* 13 |   COUNT STOPKEY                |                     |       |       |            |          |
    |  14 |    VIEW                        |                     |     2 |  9238 |     9   (0)| 00:00:01 |
    |  15 |     TABLE ACCESS BY INDEX ROWID| B_BILL              | 17395 |  3822K|     9   (0)| 00:00:01 |
    |* 16 |      INDEX FULL SCAN           | PK_B_BILL_01        |     2 |       |     8   (0)| 00:00:01 |
    ------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - filter("D"."AGENTCODE"=:B1)
       3 - access("BILLCODE"=:B1)
       5 - access("A"."CODE"=:B1)
       7 - access("A"."CODE"=:B1)
       9 - access("BILLNO"=:B1 AND "BILLCODE"=:B2 AND "FACTBILLCODE"=:B3)
      11 - access("BILLNO"=:B1 AND "BILLCODE"=:B2 AND "FACTBILLCODE"=:B3)
      12 - filter("NUM">0)
      13 - filter(ROWNUM<=1)
      16 - filter(TO_NUMBER(TRIM("BILLNO"))>=601710100010 AND 
                  TO_NUMBER(TRIM("BILLNO"))<=601710100010)

    5). 对sql语句进行分析

    1、SQL语句中有很多标量子查询,我们可以利用left join 对其改写。
    
    2、id = 1 为TABLE ACCESS FULL,表示CHAGENTBASE走的是全表扫描,在标量子查询中,主表返回多少
    行,子表也跟着被扫描多少次,所以需要对CHAGENTBASE建索引。
    
    3、SQL语句中出现TRIM(BILLNO) >= :B1 AND TRIM(BILLNO) <= :B2,导致ID = 16 为
    INDEX FULL SCAN。对主键进行索引全扫描,这种访问方式是最垃圾的。
    

    优化

    1)创建索引
    create indexIDX_CHAGENTBASE_TEST on CHAGENTBASE (AGENTCODE); 
    
    2)标量改成left join
    select *
      from (select G.*, rownum as num
              from (SELECT A.BILLNO,
                           A.BILLCODE,
                           A.GETDATE,
                           A.GETUNITCODE,
                           A.GETCODE,
                           A.GETORGANCODE,
                           A.USEORGANCODE,
                           A.USEDATE,
                           A.USEUNITCODE,
                           A.USERCODE,
                           A.CURRENCYCODE,
                           A.AMOUNT,
                           A.NAME,
                           A.NOTES,
                           A.STATUSCODE,
                           A.IFPAGEONHOLE,
                           A.OPCODE,
                           A.OPUNITCODE,
                           A.OPDATE,
                           A.LOCKTIME,
                           A.GETAGENTCODE,
                           /*                       (SELECT D.AGENTNAME
                            FROM SYN_MM_AGENTCODE_TC D
                           WHERE D.AGENTCODE = A.GETAGENTCODE) AS GETAGENTNAME*/
                           D.AGENTNAME AS GETAGENTNAME,
                           A.USEAGENTCODE,
                           A.OUTSTATUS,
                           CASE A.BILLCODE
                             WHEN 'B2010005' THEN
                              A.FACTBILLCODE
                             ELSE
                              ''
                           END FACTBILLCODE,
                           A.SALES,
                           A.FROMDATE,
                           A.TODATE,
                           /*                       (SELECT BILLNAME
                            FROM BD_BILLCODE
                           WHERE BILLCODE = A.BILLCODE) BILLNAME,*/
                           B.BILLNAME,
                           /*                       (SELECT HANDLERNAME
                            FROM BD_HANDLER
                           WHERE HANDLERCODE = A.USERCODE) USERNAME,*/
                           C.HANDLERNAME USERNAME,
                           /*                       (SELECT HANDLERNAME
                            FROM BD_HANDLER
                           WHERE HANDLERCODE = A.GETCODE) GETERNAME,*/
                           E.HANDLERNAME GETERNAME,
                           F.no3         ONLINEINVOICENO,
                           F.no4         ONLINEINVOICECODE
                      FROM B_BILL A
                      LEFT JOIN SYN_MM_AGENTCODE_TC D
                        ON D.AGENTCODE = A.GETAGENTCODE
                      LEFT JOIN BD_BILLCODE B
                        ON B.BILLCODE = A.BILLCODE
                      LEFT JOIN BD_HANDLER C
                        ON C.HANDLERCODE = A.USERCODE
                      LEFT JOIN BD_HANDLER E
                        ON E.HANDLERCODE = A.GETCODE
                      LEFT JOIN B_BILLDETAIL F
                        ON F.BILLNO = A.BILLNO
                       AND F.BILLCODE = A.BILLCODE
                       AND F.FACTBILLCODE = A.FACTBILLCODE
                     WHERE 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                       AND trim(A.BILLNO) >= '601710100010'
                       AND trim(A.BILLNO) <= '601710100010'
                       AND 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                       AND 3 > 2
                     ORDER BY A.BILLNO)G
             where rownum <= 1)
     where num > 0;
    
    Plan hash value: 1528527901
    
    ------------------------------------------------------------------------------------------------------------
    | Id  | Operation                           | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT                    |                      |     1 |  4632 |    21   (0)| 00:00:01 |
    |*  1 |  VIEW                               |                      |     1 |  4632 |    21   (0)| 00:00:01 |
    |*  2 |   COUNT STOPKEY                     |                      |       |       |            |          |
    |   3 |    VIEW                             |                      |     2 |  9238 |    21   (0)| 00:00:01 |
    |   4 |     NESTED LOOPS OUTER              |                      |     2 |   832 |    21   (0)| 00:00:01 |
    |   5 |      NESTED LOOPS OUTER             |                      |     2 |   770 |    19   (0)| 00:00:01 |
    |   6 |       NESTED LOOPS OUTER            |                      |     2 |   718 |    17   (0)| 00:00:01 |
    |   7 |        NESTED LOOPS OUTER           |                      |     2 |   614 |    12   (0)| 00:00:01 |
    |   8 |         NESTED LOOPS OUTER          |                      |     2 |   562 |    10   (0)| 00:00:01 |
    |   9 |          TABLE ACCESS BY INDEX ROWID| B_BILL               | 17395 |  3822K|     9   (0)| 00:00:01 |
    |* 10 |           INDEX FULL SCAN           | PK_B_BILL_01         |     2 |       |     8   (0)| 00:00:01 |
    |  11 |          TABLE ACCESS BY INDEX ROWID| CHAGENTBASE          |     1 |    56 |     1   (0)| 00:00:01 |
    |* 12 |           INDEX RANGE SCAN          | IDX_CHAGENTBASE_TEST |     1 |       |     0   (0)| 00:00:01 |
    |  13 |         TABLE ACCESS BY INDEX ROWID | T_EMPLOYEE_VIEW      |     1 |    26 |     2   (0)| 00:00:01 |
    |* 14 |          INDEX RANGE SCAN           | IND_T_EMPLOYEE_VIEW  |     1 |       |     1   (0)| 00:00:01 |
    |  15 |        TABLE ACCESS BY INDEX ROWID  | B_BILLDETAIL         |     1 |    52 |     3   (0)| 00:00:01 |
    |* 16 |         INDEX RANGE SCAN            | PK_B_BILLDETAIL_02   |     1 |       |     2   (0)| 00:00:01 |
    |  17 |       TABLE ACCESS BY INDEX ROWID   | T_EMPLOYEE_VIEW      |     1 |    26 |     2   (0)| 00:00:01 |
    |* 18 |        INDEX RANGE SCAN             | IND_T_EMPLOYEE_VIEW  |     1 |       |     1   (0)| 00:00:01 |
    |  19 |      TABLE ACCESS BY INDEX ROWID    | BD_BILLCODE          |     1 |    31 |     1   (0)| 00:00:01 |
    |* 20 |       INDEX UNIQUE SCAN             | PK_BD_BILLCODE       |     1 |       |     0   (0)| 00:00:01 |
    ------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - filter("NUM">0)
       2 - filter(ROWNUM<=1)
      10 - filter(TRIM("A"."BILLNO")>='601710100010' AND TRIM("A"."BILLNO")<='601710100010')
      12 - access("D"."AGENTCODE"(+)="A"."GETAGENTCODE")
      14 - access("A"."CODE"(+)="A"."GETCODE")
      16 - access("F"."BILLNO"(+)="A"."BILLNO" AND "F"."BILLCODE"(+)="A"."BILLCODE" AND 
                  "F"."FACTBILLCODE"(+)="A"."FACTBILLCODE")
      18 - access("A"."CODE"(+)="A"."USERCODE")
      20 - access("B"."BILLCODE"(+)="A"."BILLCODE")
    
    3) 把Trim去掉
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 1229065410
    
    ------------------------------------------------------------------------------------------------------------
    | Id  | Operation                           | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
    ------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT                    |                      |     1 |  4632 |    13   (0)| 00:00:01 |
    |*  1 |  VIEW                               |                      |     1 |  4632 |    13   (0)| 00:00:01 |
    |*  2 |   COUNT STOPKEY                     |                      |       |       |            |          |
    |   3 |    VIEW                             |                      |     1 |  4619 |    13   (0)| 00:00:01 |
    |   4 |     NESTED LOOPS OUTER              |                      |     1 |   416 |    13   (0)| 00:00:01 |
    |   5 |      NESTED LOOPS OUTER             |                      |     1 |   390 |    11   (0)| 00:00:01 |
    |   6 |       NESTED LOOPS OUTER            |                      |     1 |   364 |     9   (0)| 00:00:01 |
    |   7 |        NESTED LOOPS OUTER           |                      |     1 |   308 |     8   (0)| 00:00:01 |
    |   8 |         NESTED LOOPS OUTER          |                      |     1 |   277 |     7   (0)| 00:00:01 |
    |   9 |          TABLE ACCESS BY INDEX ROWID| B_BILL               |     1 |   225 |     4   (0)| 00:00:01 |
    |* 10 |           INDEX RANGE SCAN          | PK_B_BILL            |     1 |       |     3   (0)| 00:00:01 |
    |  11 |          TABLE ACCESS BY INDEX ROWID| B_BILLDETAIL         |     1 |    52 |     3   (0)| 00:00:01 |
    |* 12 |           INDEX RANGE SCAN          | PK_B_BILLDETAIL_02   |     1 |       |     2   (0)| 00:00:01 |
    |  13 |         TABLE ACCESS BY INDEX ROWID | BD_BILLCODE          |     1 |    31 |     1   (0)| 00:00:01 |
    |* 14 |          INDEX UNIQUE SCAN          | PK_BD_BILLCODE       |     1 |       |     0   (0)| 00:00:01 |
    |  15 |        TABLE ACCESS BY INDEX ROWID  | CHAGENTBASE          |     1 |    56 |     1   (0)| 00:00:01 |
    |* 16 |         INDEX RANGE SCAN            | IDX_CHAGENTBASE_TEST |     1 |       |     0   (0)| 00:00:01 |
    |  17 |       TABLE ACCESS BY INDEX ROWID   | T_EMPLOYEE_VIEW      |     1 |    26 |     2   (0)| 00:00:01 |
    |* 18 |        INDEX RANGE SCAN             | IND_T_EMPLOYEE_VIEW  |     1 |       |     1   (0)| 00:00:01 |
    |  19 |      TABLE ACCESS BY INDEX ROWID    | T_EMPLOYEE_VIEW      |     1 |    26 |     2   (0)| 00:00:01 |
    |* 20 |       INDEX RANGE SCAN              | IND_T_EMPLOYEE_VIEW  |     1 |       |     1   (0)| 00:00:01 |
    ------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - filter("NUM">0)
       2 - filter(ROWNUM<=1)
      10 - access("A"."BILLNO"='601710100010')
      12 - access("F"."BILLNO"(+)='601710100010' AND "F"."BILLCODE"(+)="A"."BILLCODE" AND
                  "F"."FACTBILLCODE"(+)="A"."FACTBILLCODE")
           filter("F"."BILLNO"(+)="A"."BILLNO")
      14 - access("B"."BILLCODE"(+)="A"."BILLCODE")
      16 - access("D"."AGENTCODE"(+)="A"."GETAGENTCODE")
      18 - access("A"."CODE"(+)="A"."GETCODE")
      20 - access("A"."CODE"(+)="A"."USERCODE")
    
    
    Statistics
    ----------------------------------------------------------
            621  recursive calls
              0  db block gets
            229  consistent gets
             17  physical reads
              0  redo size
           2937  bytes sent via SQL*Net to client
           2086  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
             16  sorts (memory)
              0  sorts (disk)
              1  rows processed

    优化效果

    可以看出消耗的 buffer cache 从之前的882,856,212.00 降到了229,效率提升了N倍.

  • 相关阅读:
    scss-变量分隔符
    scss-声明变量与引用
    scss-入门
    关于动画框架类注意的点点滴滴03
    关于动画框架类注意的点点滴滴02
    关于动画框架类注意的点点滴滴01
    简单的form表单
    简易自定义下拉菜单 与简易默认下拉html片段
    有边框的简易表格
    css模仿表格 居中
  • 原文地址:https://www.cnblogs.com/wanbin/p/9514682.html
Copyright © 2020-2023  润新知