复杂SQL性能优化的剖析(一)(r11笔记第36天)
公众号:杨建荣的学习笔记 · 作者:杨建荣 · 发布:2017-01-06 23:56:31 · 原文链接
今天本来是处理一个简单的故障,但是发现是一环套一环,花了我快一天的时间。
开始是早上收到一条报警:
报警内容: CPUutilization is too high------------------------------------报警级别: PROBLEM------------------------------------监控项目: CPU idle time:59.94 % ------------------------------------ 报警时间:2017.01.06-06:35:22开始也没有在意,准备花几分钟处理完事,但是发现这个坑越来越大。对于问题的处理,我觉得还是能够刨坑问底,你能说服自己,弄明白了,碰到类似的问题就会得心应手。
我发现数据库的负载有了较大的提升,查看快照级别的DB time负载如下:
BEGIN_SNAP END_SNAP SNAPDATE DURATION_MINS DBTIME---------- ---------- --------------------------------- ---------- 19028 19029 06 Jan 2017 00:00 60 104 19029 19030 06 Jan 2017 01:00 60 233 19030 19031 06 Jan 2017 02:00 60 331 19031 19032 06 Jan 2017 03:00 60 409 19032 19033 06 Jan 2017 04:00 60 465 19033 19034 06 Jan 2017 05:00 60 513 19034 19035 06 Jan 2017 06:00 60 538 19035 19036 06 Jan 2017 07:00 59 591 19036 19037 06 Jan 2017 08:00 60 614 19037 19038 06 Jan 2017 09:00 60 622 19038 19039 06 Jan 2017 10:00 60 665
这个情况不容乐观,很快就定位到是一个SQL语句引起的。
可以看到语句的执行计划发生了改变,本来执行2秒的语句,现在执行近5000多秒。这个差距实在是有些大了。

语句的结构如下:
merge into xxxx using
(select xxxx from h1_first_dev d, ua_td_active_log awhere d.dt = to_date(:1, 'yyyy-mm-dd')and a.dt = :2and d.deviceid is not nulland (d.deviceid = a.idfa or d.deviceid = a.mac ora.idfa =lower(utl_raw.cast_to_raw(dbms_obfuscation_toolkit.md5(input_string => d.deviceid)))) ...unionselect xxxx from h1_first_dev d, ua_td_active_log awhere d.dt = to_date(:1, 'yyyy-mm-dd')and a.dt = :2and d.deviceid is not nulland (d.deviceid = a.idfa or d.deviceid = a.mac orand (a.idfa =lower(utl_raw.cast_to_raw(dbms_obfuscation_toolkit.md5(input_string => nvl(case when instr(d.deviceid, ':') > 0 then replace(substr(substr(d.deviceid, 19, 15), 1, 15), chr(2), '') else replace(substr(d.deviceid, 1, 15), chr(2), '') end, 'null')))))....)
on(xxxx) when matched xxx
看起来语句结构也蛮复杂,而且调用了几个大家平时很少见到的包,这个时候就有两个问题需要解释清楚。
-
之前为什么没有这个问题
-
问题的解决方法是什么
查看数据库层面的活跃会话情况,可以看到有大量的会话被阻塞了,而且看阻塞的频率,语句大概是10分钟执行一次。

我对比了变化前后的执行计划情况。
