merge语句导致的性能问题紧急优化

晚上正在休息的时候,突然收到一封报警邮件。
报警内容: CPU utilization is too high
------------------------------------
报警级别: PROBLEM
------------------------------------
监控项目: CPU idle time:59.11 %
------------------------------------
这个报警信息已经非常明确,CPU使用率很紧张了。这台服务器上运行着Oracle和MySQL实例,所以第一感觉是不是MySQL的慢查询导致的,结果登录到服务器端,发现MySQL的连接数很少,没有发现慢查询,那么问题很可能就和Oracle有关系了,使用top查看,果然几个top的进程都是带有LOCAL=NO的字样,很可能是应用端触发的SQL导致。
查看v$session的信息,发现其中一个会话已经执行一条SQL超过了40分钟。这个SQL是merge语句,看来merge又摊上事了。

语句的内容如下:

我们来看看语句的执行计划情况,如下:

可以明显看到一个全表扫描,这个表中的数据大概是700多万,就算全表扫描也应该几分钟就出结果了。怎么执行了40分钟了还没有任何反应。
我们来看看执行的瓶颈在哪里。还是使用SQL Monitor来定位,一目了然。

可以明显看出瓶颈在全表扫描的部分。

表中的数据有700多万,而经过排查发现竟然没有任何索引。所以问题的原因就更加明显了。
我们需要再总结一下,问题的原因定位到了,执行计划的效率极低。怎么改进。
1.创建索引,这就无形带来几个问题,基于哪些列来创建索引
2.这个表中目前存在频繁的DML操作,如何创建索引
3.为什么执行计划的消耗如此之大
我们来一个一个看问题,首先是创建索引,这个看起来目标明确,但是具体来做,就需要一些技巧了, 对于这类的问题,个人比较偏好dbms_sqltune.report_tuning_task,因为调用方便,简单而且能很快出结果。不到1分钟分析结果就出来了,提出了3点建议,一个就是收集统计信息,一个是修改SQL Profile,还有一个就是创建索引,我们的目标明确,就是索引的改进,建议里面会根据数据的选择度来进行评估和分析,还是比较全面的。

但是创建索引的过程中,这个DDL肯定会排斥其他的DML,很容易出现这样的错误。

这种情况下,新特性ddl_lock_timeout就值得推荐了,我们可以设定一个略微长一些的超时时间,让它在后台自己去试,很快就能得到结果。

回头一看前两个问题已经解释了,那么第3个问题,为什么执行计划的差别如此之大,就算全表也不至于那么慢啊。
语句的谓词部分会做出解释:

可以看到走了filter过滤,using部分和表中的数据映射存在重大的偏差,内部的映射竟然是一大堆的case when的形式。
当然这个语句优化之后,性能提升也很明显。精确到分钟级,效果提升还是不错的。

时间: 2024-08-01 12:32:25

merge语句导致的性能问题紧急优化的相关文章

merge语句导致的CPU使用率过高的优化(二)

之前分享过一篇关于merge语句导致的CPU使用率过高优化的案例.的http://blog.itpub.net/23718752/viewspace-1819471/ 后续的跟进没有补充,也"秀"一张图,红色的火焰是原来的系统负载,右边的部分是最近的逻辑读情况,不过惭愧的是,这个不是优化的效果,因为应用的高峰期已经处理完了,后面的sql调用频率极低,所以感觉不到任何的压力.所以通过这个图也可以看出,给一张差别巨大的图也不一定是系统优化的效果,也可能是其它外在因素. 那么既然要说跟进,后

一条insert语句导致的性能问题分析(二)

今天对之前描述的问题一条insert语句导致的性能问题分析(一) 进行了进一步的补充. 有一条insert语句的主要性能瓶颈在于insert子句中的查询语句,查询中的主要资源消耗在于对两个表进行了多次关联 语句主要的结构如下: insert into xxxxx   (select * from TEST_vip_new minus select * from TEST_vip_new_bak         ) a left join TEST_vip_new_bak b         on

merge语句导致的ORA错误分析

      最近处理了好几起关于merge导致的问题,其实看到merge语句内心也还是蛮纠结的,这一次还是碰到了问题,简直无语了.       先交代下问题的背景.有一套OLTP环境和OLAP环境需要同步一部分数据,都是在每天的半夜开始,OLAP的库的一个表数据会根据增量的逻辑从OLTP库中同步,有两种方式,一种是OLAP从OLTP中去抓取,另外一种是OLTP推送给OLAP.看起来表达的意思是差不多的,实现起来就是完全不同的风格,即一种主动一种被动,而对于大部分的应用需求来看,还是更倾向于OLA

merge语句导致的CPU使用率过高的优化

今天有一个数据库有点反常,早上的时候报出了CPU使用率的警告. 警告内容如下: ZABBIX-监控系统: ------------------------------------报警内容: CPU utilization is too high ------------------------------------报警级别: PROBLEM ------------------------------------监控项目: CPU idle time:44.61 % -------------

ASP中SQL语句导致的性能问题

问题|性能|语句 今天,修改了一点上次做的办公管理系统中的文件上传的BUG,原因是ASP中SQL语句性能问题导致了RecordSet对象关闭,结果使数据入库失败.对于这个错误,我目前只能这样理解了: SQL语句 select * from TAB_FILES 打开表后,然后调用AddNew方法添加要更新的数据,表面上看没什么问题,当TAB_FILES表中记录相当多时, select * from TAB_FILES 问题就暴露了,所有被选择的数据会写入系统内存缓冲区(实际操作由RecordSet

一条insert语句导致的性能问题分析(一)

今天早上开发找我看一个问题,说他们通过程序连接去查一个表的数据的时候,只查到了8条记录,这个情况着实比较反常,因为从业务上的数据情况来说,不可能只有8条. 但是开发没有太多的权限做线上环境的数据检查,就让我帮忙看一下. 语句大概是下面这样的形式. select count(*) from TEST_VIP_LOG t where t.flag in(2,3) and insert_time >= to_date('2016-03-10','YYYY-MM-DD') and insert_time

优化-使用wm_concat导致的性能问题

问题描述 使用wm_concat导致的性能问题 sql类似如下select a.namewm_concat(a.c1)wm_concat(a.c2)wm_concat(a.c3)from table a group by a.name 这里要按名称分组将其他三个值都拼接起来,返回的都是clob类型,导致查询非常慢而且占用相当大的表空间...请教大神,这要如何优化?a.c1等拼接的值很容易超过4000... 解决方案 wm_concat的使用 解决方案二: 你的表结构不合理,你应该避免在查询的时候

采用MERGE 语句的非关联形式提升性能

      今天照例巡查垃圾sql时,发现一个跑了很长时间的sql,且其执行计划也非常的大,这个sql非常可疑,得排查排查:     第一步,照例查询内存中的执行计划: SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('17t226txddfy5',0,'advanced'));   可以看出执行计划的cost花费非常的大,且Predicate Information(即谓语)部分全是filter过滤的,怎么会没有access访问呢???????拿出其

采用MERGE语句的非关联形式提升性能 ---后传

几天前写过一篇关于merge语句的博客,由于工作忙没有关注后续的优化,今天有空了把这个补上吧.... 之前的博客地址:http://blog.itpub.net/26736162/viewspace-1218671/   关于这个sql,我们的同事终于受不了这个sql了,找我来优化,我说这个sql我之前就检测到了的,,所以已经优化好了的,你直接拿过去跑吧,[这里说明一下:由于是job,boss不让停,那没办法,只能等业务人员自己来找我了]由于最近有点忙就没有关注这个sql语句了,今天终于闲暇下来