一次ORA-01555问题分析,及SQL优化。
2018-02-01 17:33
696 查看
前言
客户说:我在数据库上继续运行昨日的脚本,但发现有个子过程在运行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_INTERMEDIARYINFO,
L_T_EDRSMT_01。
优化器错误认为
L_T_EDRSMT_01为
1条数据,两表关联,进行内连接,数据量肯定是返回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分钟内运行完成。
相关文章推荐
- 一次ORA-01555问题分析,及SQL优化。
- 一次ORA-4030问题诊断及解决【解决思路不错,说明了对象的统计信息与优化器的优化操作(即选择执行一个SQL语句在该优化参数环境下最佳的执行计划)间的关系】
- 一个Web报表项目的性能分析和优化实践(二):MySQL数据库连接不够用(TooManyConnections)问题的一次分析和解决案例
- 一次SQL优化分析的全过程
- IT咨询顾问:一次吐血的项目救火 java或判断优化小技巧 asp.net core Session的测试使用心得 【.NET架构】BIM软件架构02:Web管控平台后台架构 NetCore入门篇:(十一)NetCore项目读取配置文件appsettings.json 使用LINQ生成Where的SQL语句 js_jquery_创建cookie有效期问题_时区问题
- Mysql 优化——分析表读写和sql效率问题
- 数据库性能优化分析案例---解决SQL语句过度消耗CPU问题
- Mysql 优化——分析表读写和sql效率问题
- Mysql 优化——分析表读写和sql效率问题
- 一个Web报表项目的性能分析和优化实践(二):MySQL数据库连接不够用(TooManyConnections)问题的一次分析和解决案例
- 一个Web报表项目的性能分析和优化实践(二):MySQL数据库连接不够用(TooManyConnections)问题的一次分析和解决案例
- 性能优化分析案例---解决SQL语句过度消耗CPU问题
- 一个Web报表项目的性能分析和优化实践(二):MySQL数据库连接不够用(TooManyConnections)问题的一次分析和解决案例
- windows 上一次ora-12560 : TNS: 协议适配器错误 问题处理
- 如何优化用SQL语句INSERT INTO … SELECT插入数据时锁全表的问题
- 已解决:expdp导出带有lob字段的表,报ORA-01555错误的问题
- 关于redis性能问题分析和优化
- SQL语句练习实例之五 WMS系统中的关于LIFO或FIFO的问题分析
- 一次诊断和解决CPU利用率高的问题分析
- ORA-01000: 超出打开游标的最大数 问题的分析和解决