当前位置: 首页 > news >正文

一条执行时间两天半的sql语句简化(r4笔记第62天)

周末刚过去,今天来到办公室做例行检查,就发现一条sql语句已经执行234841秒(65小时),已经两天多了。查看了一下对应的Undo资源消耗,发现这个语句是最消undo资源的语句,一个sql语句执行这么长时间,同时对于cpu,IO都是极大的消耗。查看了undo中sql语句的占用情况。select *from ( select maxqueryid,round(sum(undoblks )*8/1024) consumed_size_MB from v$undostat group by maxqueryid order by consumed_size_MB desc ) where rownum<50;MAXQUERYID CONSUMED_SIZE_MB------------- ----------------4ad8ypr3nf6vm 113178ftmvqxfzq1fv0 70343通过sql_monitor抓取的执行情况如下:IO Requests发送了近97M次,差不多有751.2G了。

Buffer GetsIO RequestsDatabase TimeWait Activity

.

632M

.

97M

.

.

238254s

.

.

100%

对应的sql语句如下:SELECT trim(TO_CHAR(COUNT(distinct coll.entity_id), '000000000')) FROM cl1_coll_entity coll, table_bpm_step_inst bpm, table_bpm_step, ar1_account, csm_account, csm_pay_channel, (SELECT account_id FROM ar1_aged_trial_balance, logical_date, cl1_coll_entity WHERE aged_type = 'D' AND group_type = 'B' AND status = 'EFF' AND logical_date.logical_date_type = 'R' AND TRUNC(logical_date - due_date) >= 0 --and logical_date.expiration_date is null AND account_id = entity_id GROUP BY account_id) ar1_aged_trial_balance, (SELECT account_id, due_date FROM (SELECT ar1_aged_trial_balance.*, -- FROM (SELECT ar1_aged_trial_balance.account_id,ar1_aged_trial_balance.due_date, ROW_NUMBER() OVER(PARTITION BY account_id ORDER BY due_date) AS RANK FROM ar1_aged_trial_balance WHERE status = 'EFF' AND aged_type = 'D' AND group_type = 'B') WHERE RANK = 1) due_detail, customer, subscriber, ar1_billing_arrangement, ar1_address_name, charge_distribute WHERE coll.entity_id(+) = csm_account.ban AND coll.proc_inst_id = bpm.parent2proc_inst AND bpm.step2step = table_bpm_step.objid AND bpm.status = 30 AND coll.entity_id = ar1_account.account_id AND csm_account.ban = csm_pay_channel.ban AND ar1_account.account_id = ar1_aged_trial_balance.account_id AND csm_account.customer_id = customer.customer_id AND csm_account.customer_id = subscriber.customer_id AND ar1_account.account_id = ar1_billing_arrangement.account_id AND ar1_account.account_id = ar1_address_name.account_id AND ar1_address_name.address_type = 'ACC' AND coll.entity_id = due_detail.account_id AND subscriber.trx_id = charge_distribute.trx_id AND subscriber.subscriber_no = charge_distribute.agreement_no AND charge_distribute.target_pcn = csm_pay_channel.pym_channel_no AND csm_account.ban = csm_pay_channel.ban AND EXISTS (SELECT cl1_treatment_activity.entity_id FROM cl1_treatment_activity, table_bpm_step_inst, table_bpm_step WHERE cl1_treatment_activity.step_id = table_bpm_step_inst.objid AND table_bpm_step_inst.step2step = table_bpm_step.objid AND table_bpm_step.NAME LIKE '%IVR%' AND table_bpm_step_inst.status = 65 AND TO_DATE(TO_CHAR(cl1_treatment_activity.activity_date, 'YYYYMMDD'), 'YYYYMMDD') = (SELECT logical_date FROM logical_date WHERE logical_date_type = 'R' AND expiration_date IS NULL) AND cl1_treatment_activity.entity_id = csm_account.ban)

对应的执行计划如下:| 39 | TABLE ACCESS FULL | AR1_AGED_TRIAL_BALANCE | 25M| 585M| | 184K (2)| 56 | TABLE ACCESS FULL | AR1_AGED_TRIAL_BALANCE | 25M| 488M| | 184K (2) (SELECT account_id FROM ar1_aged_trial_balance, logical_date, cl1_coll_entity WHERE aged_type = 'D' AND group_type = 'B' AND status = 'EFF' AND logical_date.logical_date_type = 'R' AND TRUNC(logical_date - due_date) >= 0 and logical_date.expiration_date is null AND account_id = entity_id GROUP BY account_id) ar1_aged_trial_balance, (SELECT account_id, due_date FROM (SELECT ar1_aged_trial_balance.*, ROW_NUMBER() OVER(PARTITION BY account_id ORDER BY due_date) AS RANK FROM ar1_aged_trial_balance WHERE status = 'EFF' AND aged_type = 'D' AND group_type = 'B') WHERE RANK = 1) due_detail

-- AND coll.entity_id = due_detail.account_id

子查询ar1_aged_trial_balance的account_id字段和ar1_account字段关联,而另外一个子查询due_detail的account_id字段和coll.entity_id关联,结合这个条件 coll.entity_id = ar1_account.account_id

从这个思路来看,因为子查询ar1_aged_trial_balance和due_detail没有其它的关联条件,唯一需要用到的信息就是account_id

aged_type = 'D' AND group_type = 'B' AND status = 'EFF' -- ar1_aged_trial_balance, /* (SELECT account_id, due_date FROM (SELECT ar1_aged_trial_balance.*, -- FROM (SELECT ar1_aged_trial_balance.account_id,ar1_aged_trial_balance.due_date, ROW_NUMBER() OVER(PARTITION BY account_id ORDER BY due_date) AS RANK FROM ar1_aged_trial_balance WHERE status = 'EFF' AND aged_type = 'D' AND group_type = 'B') WHERE RANK = 1) due_detail,*/-- AND ar1_account.account_id = ar1_aged_trial_balance.account_id-- AND coll.entity_id = due_detail.account_id and exists( (SELECT 1 FROM ar1_aged_trial_balance--, logical_date--, cl1_coll_entity WHERE aged_type = 'D' AND group_type = 'B' AND status = 'EFF' -- AND logical_date.logical_date_type = 'R' AND TRUNC(tmp_logical_date.logical_date - due_date) >= 0 --and logical_date.expiration_date is null --added AND account_id = coll.entity_id --GROUP BY account_id )

总体cost 在167K,完整的执行计划可以查看原文。|* 46 | INDEX RANGE SCAN | AR1_AGED_TRIAL_BALANCE_2IX | 12 | | | 80 (0)| 00:00:01 | 1 | 401 |

通过这个例子,我们可以看到,一个看似很复杂的sql语句,如果对症下药,抓住性能瓶颈,就可能通过简化sql语句的方式来达到大幅度的性能提升。

相关文章:

  • 通过pl/sql来格式化sql(r4笔记第63天)
  • java中的序列化 (r4笔记第64天)
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • 通过shell脚本快速定位active session问题(r4笔记第65天)
  • 重温二分查找算法(r4笔记第66天)
  • 不要成为技术的奴隶(一) (r4笔记第67天)
  • 最简单的web服务器实现(一)(r4笔记第68天)
  • 通过编程控制CPU利用率(r4笔记第69天)
  • 通过图表简化sql语句的表关联(r4笔记第70天)
  • 巧用外部表避免大量的insert (r4笔记第71天)
  • 海量数据迁移之数据抽取流程 (r4笔记第72天)
  • 重温快速排序(r4笔记第73天)
  • 海量数据迁移之sqlldr和datapump的缺点分析(r4笔记第74天)
  • mongoDB初探第一篇(r4笔记第75天)
  • 通过单例模式模拟RAC连接 (r4笔记第76天)
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • 【刷算法】求1+2+3+...+n
  • Android Studio:GIT提交项目到远程仓库
  • input实现文字超出省略号功能
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • Java应用性能调优
  • php面试题 汇集2
  • windows-nginx-https-本地配置
  • 从0到1:PostCSS 插件开发最佳实践
  • 高程读书笔记 第六章 面向对象程序设计
  • 关于Java中分层中遇到的一些问题
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 三栏布局总结
  • 深度学习在携程攻略社区的应用
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 责任链模式的两种实现
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (solr系列:一)使用tomcat部署solr服务
  • (超详细)语音信号处理之特征提取
  • (二)fiber的基本认识
  • (二)学习JVM —— 垃圾回收机制
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (接口封装)
  • (九)One-Wire总线-DS18B20
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • ****Linux下Mysql的安装和配置
  • .bat批处理(二):%0 %1——给批处理脚本传递参数
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .NET MVC第五章、模型绑定获取表单数据
  • .NET 除了用 Task 之外,如何自己写一个可以 await 的对象?
  • .NET处理HTTP请求
  • /*在DataTable中更新、删除数据*/
  • /etc/apt/sources.list 和 /etc/apt/sources.list.d
  • [ 攻防演练演示篇 ] 利用通达OA 文件上传漏洞上传webshell获取主机权限