• 一次ORA-01555问题分析,及SQL优化。


    前言

    客户说:
    我在数据库上继续运行昨日的脚本,但发现有个子过程在运行10个小时后报错:
    烦请协助看看。。。
    错误码是:ORA-01555: snapshot too old: rollback segment number 6 with name “_SYSSMU6$” too small
    ORA-02063: preceding line from CLONE
    这里写图片描述

    分析

    发生ORA-01555错误,一般是因为数据库内部,有长SQL在运行,运行时间超过undo保存数据的时间。Clone库undo保存数据的时间为:18000s。

    根据错误提示,找到对应的SQL:

    INSERT INTO   L_T_EDRSMT_RVII
    SELECT DISTINCT T1.topactualid,
                    T1.INTERMEDIARYCODE,
                    T1.INTERMEDIARYTYPE,
                    nvl(tt.policypremiumchange, 0) / 100 *
                    (nvl(t1.commissionrate, 0) / 100) *
                    nvl(T3.EXECHANGERATE, 100) AS COMMISSIONAOMUNT
    -- SUM(NVL(T1.COMMISSIONAOMUNT, 0) / 100 * nvl(T3.EXECHANGERATE, 100)) AS COMMISSIONAOMUNT
      FROM tcsa.ROLE_V_INTERMEDIARYINFO T1
     INNER JOIN tcsa.role_v_premiuminvolved tt
        ON t1.topactualid = tt.topactualid
     INNER JOIN circ_audit.L_T_EDRSMT_01 LT
        ON LT.topactualid = T1.topactualid
      LEFT OUTER JOIN tcsa.Uccexchange T3
        ON T1.CURRENCYCODE = T3.EXCHANGECURRENCY
       AND TO_CHAR(t3.issuancedate, 'YYYYMMDD') =
           TO_CHAR(LT.T_INSRNC_BGN_TM, 'YYYYMM') || '01'
       AND T3.basecurrency = '$$100001000001'
    
     执行计划:
     Plan hash value: 343405098
    
    --------------------------------------------------------------------------------------------------------------------------------------
    | Id  | Operation                          | Name                    | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     | Inst   |IN-OUT|
    --------------------------------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT                   |                         |    26 |   156K|       |  6378   (1)| 00:01:17 |        |      |
    |   1 |  HASH UNIQUE                       |                         |    26 |   156K|       |  6378   (1)| 00:01:17 |        |      |
    |*  2 |   HASH JOIN OUTER                  |                         |    26 |   156K|       |  6377   (1)| 00:01:17 |        |      |
    |   3 |    VIEW                            |                         |     1 |  6058 |       |  5598   (1)| 00:01:08 |        |      |
    |*  4 |     HASH JOIN                      |                         |     1 |  6123 |       |  5598   (1)| 00:01:08 |        |      |
    |   5 |      NESTED LOOPS                  |                         |     1 |  6097 |       |  5596   (1)| 00:01:08 |        |      |
    |   6 |       MERGE JOIN CARTESIAN         |                         |     1 |  6071 |       |  5593   (1)| 00:01:08 |        |      |
    |   7 |        NESTED LOOPS                |                         |     1 |  6058 |       |     1 (100)| 00:00:01 |        |      |
    |   8 |         VIEW                       | ROLE_V_INTERMEDIARYINFO |   100 |   589K|       |     1 (100)| 00:00:01 |        |      |
    |   9 |          REMOTE                    |                         |       |       |       |            |          |  CLONE | R->S |
    |  10 |         TABLE ACCESS BY INDEX ROWID| L_T_EDRSMT_01           |     1 |    26 |       |     0   (0)| 00:00:01 |        |      |
    |* 11 |          INDEX RANGE SCAN          | IDX_L_T_EDRSMT_01_01    |     1 |       |       |     0   (0)| 00:00:01 |        |      |
    |  12 |        BUFFER SORT                 |                         |   370K|  4702K|       |  5593   (1)| 00:01:08 |        |      |
    |  13 |         REMOTE                     | POLICY                  |   370K|  4702K|       |  5592   (1)| 00:01:08 |  CLONE | R->S |
    |  14 |       REMOTE                       | PREMIUMINVOLVED         |     1 |    26 |       |     3   (0)| 00:00:01 |  CLONE | R->S |
    |  15 |      VIEW                          |                         |   100 |  2600 |       |     1 (100)| 00:00:01 |        |      |
    |  16 |       REMOTE                       |                         |       |       |       |            |          |  CLONE | R->S |
    |* 17 |    VIEW                            |                         | 31006 |  3512K|       |   778   (1)| 00:00:10 |        |      |
    |* 18 |     WINDOW SORT PUSHED RANK        |                         | 31006 |  2815K|  6632K|   778   (1)| 00:00:10 |        |      |
    |  19 |      REMOTE                        | UCCEXCHANGE             | 31006 |  2815K|       |   111   (1)| 00:00:02 |  CLONE | R->S |
    --------------------------------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - access(TO_CHAR("ISSUANCEDATE"(+),'YYYYMMDD')=TO_CHAR(INTERNAL_FUNCTION("LT"."T_INSRNC_BGN_TM"),'YYYYMM')||'01' AND 
                  "T1"."CURRENCYCODE"="EXCHANGECURRENCY"(+))
       4 - access("B"."ACTUALID"="A"."ROLEID")
      11 - access("LT"."TOPACTUALID"="T1"."TOPACTUALID")
      17 - filter("RN"(+)=1)
      18 - filter(ROW_NUMBER() OVER ( PARTITION BY "T_RMB"."BASECURRENCY","T_RMB"."EXCHANGECURRENCY",TO_DATE(TO_CHAR(INTERNAL_FUNC
                  TION("T_RMB"."ISSUANCEDATE"),'yyyymmdd'),'yyyymmdd') ORDER BY "STATUS")<=1)

    观察执行计划,发现id=6处关键字为MERGE JOIN CARTESIAN,也就是笛卡尔积

    笛卡儿积一般发生在: 两个表关联没有连接条件的时候就会产生笛卡尔笛卡儿积,这种表连接方式就叫笛卡尔笛卡儿连接。
    笛卡尔连接会返回两个表的乘积。A有100行数据,B有14行数据,两个表进行笛卡尔连接之后会返回1400行数据

    那在这个执行计划中,为什么优化器会选择笛卡尔积连接呢?

    因为Id=7返回的Rows被优化器错误的估算为1行,优化器认为1行的表与任意大小的表进行笛卡尔关联,数据也不会翻翻,优化器认为这是安全的。所以这里优化器选择了笛卡尔连接。

    ID = 7 为NEST LOOPS 内连接嵌套循环关联方式,所关联的两张表为ROLE_V_INTERMEDIARYINFOL_T_EDRSMT_01

    优化器错误认为L_T_EDRSMT_011条数据,两表关联,进行内连接,数据量肯定是返回1行。 而实际上,我们在数据库中查询此表,发现数据量有16549行数据
    这里写图片描述
    所以说此处执行计划是错误的

    但是为什么,优化器会认为L_T_EDRSMT_01为1条数据呢?

    因为数据库统计信息收集的不准。但是为什么收集的不准?

    因为运行此存储过程SP_AUDIT_T_EDRSMT之前,恰好这张表L_T_EDRSMT_01的数据为0。每天晚上10点数据库内部定时,收集统计信息时,也就把表的的统计信息收集为0了。

    优化方法

    重新收集统计信息

    BEGIN
      DBMS_STATS.gather_schema_stats(ownname          => 'CIRC_AUDIT',
                                    estimate_percent => 30,
                                    method_opt       => 'for all columns size repeat',
                                    no_invalidate    => FALSE,
                                    degree           => 4,
                                    granularity      => 'ALL',     
                                    cascade          => TRUE);
    END;
    /
    

    收集完成后,该SQL能在10分钟内运行完成。

  • 相关阅读:
    SQL语句基础之 单表查找
    SQL语句基础之 管理数据库,表 和 数据
    JavaWeb之 JSP:自定义标签
    JavaWeb之 JSP:内置对象,EL表达式,JSP标签基础
    JavaWeb之 JSP基础
    JavaWeb之Servlet:Cookie 和 Session
    JavaWeb之Servlet: ServletConfig 与 ServletContext
    JavaWeb之 Servlet执行过程 与 生命周期
    JavaWeb之Servlet:请求 与 响应
    Vue.js中 watch(深度监听)的最易懂的解释
  • 原文地址:https://www.cnblogs.com/wanbin/p/9514707.html
Copyright © 2020-2023  润新知