前言

客户说,生产系统最近CPU使用率经常达到100%,请DBA帮忙调查一下。

根据客户提供的情况描述及对应时间段,我导出AWR,发现如下问题:



11v41vaj06pjd :每次执行消耗2,378,874.14 buffer 约等于18g 内存

bsfrz471nh9s4:每次执行消耗1,545,875.18 buffer 约等于12g 内存

非常大的内存消耗,而且执行频率高。

所以就断定这两条sql就是cpu使用率高的祸源,只要优化这两条sql,cpu必然而然的降下来。

优化前

这两条sql的结构是一样的,只是表连接有所不同,所以优化方法都是一致的。

update mm_writeoutstatus_to s
set s.status = '00'
where s.status = '0Z'
and s.id in (select distinct t.id
from mm_writeout_to t, mm_paymentin_events_td p
where exists (select 1
from mm_paymentin_events_td m,
mm_paymentin_events_td m1
where m.newno = 1420467997
and m.fatherno = m1.listno
and m1.sonno = p.listno)
and t.businessno = p.newno); Execution Plan
----------------------------------------------------------
Plan hash value: 393324829 --------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | 21 | 4437 (1)| 00:00:54 |
| 1 | UPDATE | MM_WRITEOUTSTATUS_TO | | | | |
|* 2 | FILTER | | | | | |
| 3 | TABLE ACCESS BY INDEX ROWID | MM_WRITEOUTSTATUS_TO | 789 | 16569 | 96 (0)| 00:00:02 |
|* 4 | INDEX RANGE SCAN | IDX_WRITEOUTSTATUS_TEST | 789 | | 6 (0)| 00:00:01 |
| 5 | NESTED LOOPS | | 1 | 52 | 11 (0)| 00:00:01 |
| 6 | NESTED LOOPS | | 1 | 38 | 9 (0)| 00:00:01 |
| 7 | NESTED LOOPS | | 1 | 27 | 7 (0)| 00:00:01 |
| 8 | TABLE ACCESS BY INDEX ROWID| MM_WRITEOUT_TO | 1 | 18 | 3 (0)| 00:00:01 |
|* 9 | INDEX UNIQUE SCAN | PK_MM_WRITEOUT_TO | 1 | | 2 (0)| 00:00:01 |
|* 10 | TABLE ACCESS BY INDEX ROWID| MM_PAYMENTIN_EVENTS_TD | 1 | 9 | 4 (0)| 00:00:01 |
|* 11 | INDEX RANGE SCAN | IDX_PAYMENTINE_08 | 4 | | 2 (0)| 00:00:01 |
|* 12 | TABLE ACCESS BY INDEX ROWID | MM_PAYMENTIN_EVENTS_TD | 1 | 11 | 2 (0)| 00:00:01 |
|* 13 | INDEX UNIQUE SCAN | PK_MM_PAYMENTIN_EVENTS_TD | 1 | | 1 (0)| 00:00:01 |
|* 14 | TABLE ACCESS BY INDEX ROWID | MM_PAYMENTIN_EVENTS_TD | 1 | 14 | 2 (0)| 00:00:01 |
|* 15 | INDEX UNIQUE SCAN | PK_MM_PAYMENTIN_EVENTS_TD | 1 | | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id):
--------------------------------------------------- 2 - filter( EXISTS (SELECT 0 FROM "MM_PAYMENTIN_EVENTS_TD" "P","MM_WRITEOUT_TO"
"T","MM_PAYMENTIN_EVENTS_TD" "M1","MM_PAYMENTIN_EVENTS_TD" "M" WHERE "M"."NEWNO"=1420467997 AND
"M"."FATHERNO" IS NOT NULL AND "M"."FATHERNO"="M1"."LISTNO" AND "M1"."SONNO" IS NOT NULL AND
"T"."ID"=:B1 AND "M1"."SONNO"="P"."LISTNO" AND "P"."NEWNO"=TO_NUMBER("T"."BUSINESSNO")))
4 - access("S"."STATUS"='0Z')
9 - access("T"."ID"=:B1)
10 - filter("M"."FATHERNO" IS NOT NULL)
11 - access("M"."NEWNO"=1420467997)
12 - filter("M1"."SONNO" IS NOT NULL)
13 - access("M"."FATHERNO"="M1"."LISTNO")
14 - filter("P"."NEWNO"=TO_NUMBER("T"."BUSINESSNO"))
15 - access("M1"."SONNO"="P"."LISTNO") Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
1830312 consistent gets
154 physical reads
0 redo size
830 bytes sent via SQL*Net to client
1240 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
0 rows processed

分析

执行计划中有走filter关键字,且有两个子级,我们都知道,走这种连接方式是非常耗费性能的,主表返回多少行,被驱动表就得被扫描多少次。

利用merge into 可以等价改写update语句。

优化后

merge into  mm_writeoutstatus_to s
using (select distinct t.id
from mm_writeout_to t, mm_paymentin_events_td p
where exists (select 1
from mm_paymentin_events_td m,
mm_paymentin_events_td m1
where m.newno = 1420467997
and m.fatherno = m1.listno
and m1.sonno = p.listno)
and t.businessno = p.newno)b
on (s.id = b.id)
when matched then
update set s.status = '00' where s.status = '0Z' Execution Plan
----------------------------------------------------------
Plan hash value: 1386952490 ------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------------------
| 0 | MERGE STATEMENT | | 1 | 59 | 9822 (1)| 00:01:58 |
| 1 | MERGE | MM_WRITEOUTSTATUS_TO | | | | |
| 2 | VIEW | | | | | |
| 3 | TABLE ACCESS BY INDEX ROWID | MM_WRITEOUTSTATUS_TO | 1 | 53 | 3 (0)| 00:00:01 |
| 4 | NESTED LOOPS | | 1 | 66 | 9822 (1)| 00:01:58 |
| 5 | VIEW | | 1 | 13 | 9819 (1)| 00:01:58 |
| 6 | SORT UNIQUE | | 1 | 52 | 9819 (1)| 00:01:58 |
|* 7 | HASH JOIN | | 1 | 52 | 9818 (1)| 00:01:58 |
| 8 | NESTED LOOPS | | 1 | 34 | 9 (0)| 00:00:01 |
| 9 | NESTED LOOPS | | 1 | 20 | 7 (0)| 00:00:01 |
|* 10 | TABLE ACCESS BY INDEX ROWID| MM_PAYMENTIN_EVENTS_TD | 1 | 9 | 5 (0)| 00:00:01 |
|* 11 | INDEX RANGE SCAN | IDX_PAYMENTINE_08 | 4 | | 3 (0)| 00:00:01 |
|* 12 | TABLE ACCESS BY INDEX ROWID| MM_PAYMENTIN_EVENTS_TD | 1 | 11 | 2 (0)| 00:00:01 |
|* 13 | INDEX UNIQUE SCAN | PK_MM_PAYMENTIN_EVENTS_TD | 1 | | 1 (0)| 00:00:01 |
| 14 | TABLE ACCESS BY INDEX ROWID | MM_PAYMENTIN_EVENTS_TD | 1 | 14 | 2 (0)| 00:00:01 |
|* 15 | INDEX UNIQUE SCAN | PK_MM_PAYMENTIN_EVENTS_TD | 1 | | 1 (0)| 00:00:01 |
| 16 | TABLE ACCESS FULL | MM_WRITEOUT_TO | 1124K| 19M| 9797 (1)| 00:01:58 |
|* 17 | INDEX RANGE SCAN | IDX_WRITEOUTSTATUS_1 | 1 | | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id):
--------------------------------------------------- 7 - access("P"."NEWNO"=TO_NUMBER("T"."BUSINESSNO"))
10 - filter("M"."FATHERNO" IS NOT NULL)
11 - access("M"."NEWNO"=1420467997)
12 - filter("M1"."SONNO" IS NOT NULL)
13 - access("M"."FATHERNO"="M1"."LISTNO")
15 - access("M1"."SONNO"="P"."LISTNO")
17 - access("S"."ID"="B"."ID") Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
54083 consistent gets
0 physical reads
0 redo size
832 bytes sent via SQL*Net to client
1281 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
0 rows processed ------------------------------------------------------------------------------------------------------------------------------

优化前每次执行需要1830312 次逻辑读,优化后每次执行需要54083 次逻辑读,性能提升33.8倍

利用Merge into 改写Update SQL 一例的更多相关文章

  1. PLSQL_性能优化系列17_Oracle Merge Into和Update更新效率

    2015-05-21 Created By BaoXinjian 一.摘要 以前只考虑 merge into 只是在特定场合下方便才使用的,今天才发现,merge into 竟然会比 update 在 ...

  2. merge into 和 update 的效率对比

    以前只考虑 merge into 只是在特定场合下方便才使用的,今天才发现,merge into 竟然会比 update 在更新数据时有这么大的改进.其实呢,merge into部分的update和u ...

  3. UPDATE sql 优化

    一个网友说他的存储过程中有一段update sql,运行了15分钟还没出结果,需要优化一下 他把sql发给我 UPDATE TB_RESULT R SET R.VOTE_COUNT=NVL(( SEL ...

  4. what a fuck postgre update sql

    ================= what a fuck postgre update sql ================= UPDATE temp_group_temp set group_ ...

  5. Could not execute JDBC batch update; SQL [delete from role where roleId=?]; constraint [null]; neste

    今天在写多个删除功能的时候出现了这么一个错误:意思是删除操作的时候,没有找到对应的外键. Cannot delete or update a parent row: a foreign key con ...

  6. 利用闭包特性改写addEventListener的回调函数

    var numClicks = 0; document.addEventListener("click",function(){ alert( ++numClicks); },fa ...

  7. MySql update inner join!MySql跨表更新 多表update sql语句?如何将select出来的部分数据update到另一个表里面?

    项目中,评论数,关注数等数据,是实时更新的.+1,-1 这种. 有的时候,可能统计不准确. 需要写一个统计工具,更新校准下. 用Java写SQL和函数,代码很清晰,方便扩展,但是太慢了. 为了简单起见 ...

  8. C#备份及还原数据库的实现代码(粗略) // 利用C#还原数据库(SQL SERVER)备份文件到指定路径

    C#数据库备份及还原 1.在用户的配置时,我们需要列出当前局域网内所有的数据库服务器,并且要列出指定服务器的所有数据库,实现代码如下: 取得数据库服务器列表: public ArrayList Get ...

  9. 大型面试现场:一条update sql执行都经历什么?

    导读 Hi,大家好!我是白日梦!本文是MySQL专题的第 24 篇. 今天我要跟你分享的MySQL话题是:"从一条update sql执行都经历什么开始,发散开一系列的问题,看看你能抗到第几 ...

随机推荐

  1. Wait示例分析

    wait方法使"当前线程"进入阻塞(等待)状态. 示例分析: public class TestWait { public static void main(String[] ar ...

  2. Hardcoded string "下一步", should use @string resource警告 (转载)

    转自:http://blog.csdn.net/iqv520/article/details/7579513 在布局文件中,文本的设置使用如下写法时会有警告:Hardcoded string &quo ...

  3. 洛谷 P1083 借教室【二分+差分/线段树】

    二分mid,然后用1~mid的操作在差分序列上加减,最后把差分序列前缀和起来,看是否有有超过初始r值的 #include<iostream> #include<cstdio> ...

  4. 【练习总结】题目:筛法遍历素数(Java)

    初学Java,学到流程控制的循环,有个练习题是暴力遍历素数. 因为看过av32186751,知道有个筛法,就想试试. 又受到线性筛法(一)--素数筛法(一) - nerd呱呱 - 博客园中,的这段启发 ...

  5. 三种实现AJAX的方法以及Vue和axios结合使用的坑

    前言 之前曾经想自己写一个天气的App,并找到了一个免费的天气数据接口的服务商--和风天气,当时也不懂怎么发HTTP请求,而且也只会用Java语言,看到官方文档里面有一个Java代码示例,就复制了一下 ...

  6. 升级Python后, yum不能用了

    yum需要使用python2,而升级python3后,就会导致语法错误 更正方法: sudo vim /usr/bin/yum 然后把第一行的python改成python2就好了 之后如果出现类似的, ...

  7. hasLayout原理【转】

    项目中经常用到:*html .clearfix{ height:1%;}  //IE6能识别*+html .clearfix{height:1%;} //IE7能识别1,有很多方式能触发hasLayo ...

  8. 题解报告:hdu 1039 Easier Done Than Said?

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1039 Problem Description Password security is a trick ...

  9. Apusic中间件结合MyEclipse进行远程调试记录

    Apusic中间件结合MyEclipse进行远程调试记录. 在金蝶域中正常部署应用. 启动金蝶中间件时使用"startapusic -ds"命令. 在MyEclipse的Run-- ...

  10. SolrCloud索引富文本数据

    solrconfig配置文件: schema配置文件: 执行目录: /opt/solr-5.5.4/server/scripts/cloud-scripts -- 下载配置文件 ./zkcli.sh ...