利用Merge into 改写Update SQL 一例
前言
客户说,生产系统最近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 一例的更多相关文章
- PLSQL_性能优化系列17_Oracle Merge Into和Update更新效率
2015-05-21 Created By BaoXinjian 一.摘要 以前只考虑 merge into 只是在特定场合下方便才使用的,今天才发现,merge into 竟然会比 update 在 ...
- merge into 和 update 的效率对比
以前只考虑 merge into 只是在特定场合下方便才使用的,今天才发现,merge into 竟然会比 update 在更新数据时有这么大的改进.其实呢,merge into部分的update和u ...
- UPDATE sql 优化
一个网友说他的存储过程中有一段update sql,运行了15分钟还没出结果,需要优化一下 他把sql发给我 UPDATE TB_RESULT R SET R.VOTE_COUNT=NVL(( SEL ...
- what a fuck postgre update sql
================= what a fuck postgre update sql ================= UPDATE temp_group_temp set group_ ...
- 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 ...
- 利用闭包特性改写addEventListener的回调函数
var numClicks = 0; document.addEventListener("click",function(){ alert( ++numClicks); },fa ...
- MySql update inner join!MySql跨表更新 多表update sql语句?如何将select出来的部分数据update到另一个表里面?
项目中,评论数,关注数等数据,是实时更新的.+1,-1 这种. 有的时候,可能统计不准确. 需要写一个统计工具,更新校准下. 用Java写SQL和函数,代码很清晰,方便扩展,但是太慢了. 为了简单起见 ...
- C#备份及还原数据库的实现代码(粗略) // 利用C#还原数据库(SQL SERVER)备份文件到指定路径
C#数据库备份及还原 1.在用户的配置时,我们需要列出当前局域网内所有的数据库服务器,并且要列出指定服务器的所有数据库,实现代码如下: 取得数据库服务器列表: public ArrayList Get ...
- 大型面试现场:一条update sql执行都经历什么?
导读 Hi,大家好!我是白日梦!本文是MySQL专题的第 24 篇. 今天我要跟你分享的MySQL话题是:"从一条update sql执行都经历什么开始,发散开一系列的问题,看看你能抗到第几 ...
随机推荐
- ubuntu 12.04 samba 配置(转载)
转自:http://blog.sina.com.cn/s/blog_a5b607f801013av9.html 首先当然是要安装samba了,呵呵: 代码: sudo apt-get install ...
- bzoj 1997: [Hnoi2010]Planar【瞎搞+黑白染色】
脑补一下给出的图:一个环,然后有若干连接环点的边,我们就是要求这些边不重叠 考虑一下不重叠的情况,两个有交边一定要一个在环内一个在环外,所以把相交的边连边,然后跑黑白染色看是否能不矛盾即可(可能算个2 ...
- Word Cloud (词云) - Python
>>What's Word Cloud 词云 (Word Cloud)是对文本中出现频率较高的词语给予视觉化展示的图形, 是一种常见的文本挖掘的方法.目前已有多种数据分析工具支持这种图形, ...
- 水题不AC,自挂二叉树——Chemist
学长让我们刷USACO的水题果然是有道理的,做了四道挂了两道...细节处理一定要小心!大概都是NOIP Day1 T1的难度,但是一定要考虑全面否则还是凉凉啊. 一.USACO1.1贪婪的送礼者 题目 ...
- [BZOJ3531] Peaks加强版
Peaks Peaks 加强版 Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越 ...
- 配置Ubuntu16.04第01步:U盘安装 Ubuntu 16.04系统
Ubuntu 每年发布两个版本,Ubuntu 16.04 开发代号为“Xenial Xerus”,为第六个长期支持(LTS)版本. 1. 制作U盘系统安装盘 1.1下载最新的Universal USB ...
- 利用Marshal.AllocHGlobal申请非托管内存,unsafe代码
unsafe public class RUN { int[] array3; IntPtr handle; ; public RUN() { handleCount = * ; handle = S ...
- CoreText的使用方法
- (void)draw { CGContextRef context = UIGraphicsGetCurrentContext(); NSMutableAttributedString *attr ...
- 静态代理,jdbc动态代理和cglib动态代理
静态代理 1.定义抽象主题接口. package com.zhangguo.Spring041.aop02; /** * 接口 * 抽象主题 */ public interface IMath { / ...
- 【数据分析 R语言实战】学习笔记 第一章 数据分析导引
1.1数据分析概述 1.1.1数据分析的原则 (1)数据分析是为了验证假设的问题,需要提供必要的数据验证.在数据分析中,分析模型构建完成后,需要利用测试数据验证模型的正确性. (2)数据分析是为了挖掘 ...