前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一条insert语句导致的性能问题分析(二)(r8笔记第43天)

一条insert语句导致的性能问题分析(二)(r8笔记第43天)

作者头像
jeanron100
发布2018-03-19 13:56:26
5750
发布2018-03-19 13:56:26
举报
文章被收录于专栏:杨建荣的学习笔记

今天对之前描述的问题一条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 a.cn=b.cn 对于这个test_vip_new和test_vip_new_bak我产生了疑问,觉得这个临时表test_vip_new_bak有些多余。带着这种思路分析,看起来逻辑很简单啊,于是就联系了开发的同学,一起讨论一番。 但是讨论完之后,还是让我有些不知所措。 首先,语句为什么要多次关联,自己做了一个小的测试,感觉这种关联方式还是有些多余。 SQL> create table a (id number); Table created. SQL> create table b (id number); Table created. SQL> insert into a values(1); 1 row created. SQL> insert into a values(2); 1 row created. SQL> insert into b values(1); 1 row created. SQL> select * from a minus select * from b; ID ---------- 2 SQL> select *from a left join b on a.id=b.id; ID ID ---------- ---------- 1 1 2 如果按照这样的思路,仿照原来的结构输出就是下面这样的结果。 SQL> select *from (select * from a minus select * from b) a left join b on a.id=b.id; ID ID ---------- ---------- 2 但是和开发讨论了一番,发现我的想法有些简单了,具体的场景中数据过滤的逻辑比上面这种略微复杂一些。 通过一个两个测试表来模拟。 create table a (id1 number,id2 number);create table game_new (id1 number,id2 number); create table game_new_bak (id1 number,id2 number); 如果原来的数据内容为(1,1),在运行存储过程之后,会修改为(1,2) SQL> insert into game_new values(1,2); 1 row created. 然后存储过程在运行过程中,会插入一些新的数据,假设为(2,2) SQL> insert into game_new values(2,2); 1 row created. 而临时表game_new_bak中的数据是存储过程运行之前的数据状态,即(1,1) SQL> insert into game_new_bak values(1,1); 1 row created. 按照这种情况,两个表做了minus操作之后会输出两行,即修改之后的数据和新增的数据。 而这个需求需要实现的是,根据id1进行匹配,把修改前的id2一并输出。这样就知道修改前是什么样的数据了,如果是新增的,那这列的值就保持为空。 SQL> select a.id1,a.id2,b.id2 from (select * from game_new minus select *from game_new_bak) a left join game_new_bak b on a.id1=b.id1 ID1 ID2 ID2 ---------- ---------- ---------- 1 2 1 2 2 如果是这样的情况,就完全可以使用一次表关联就可以改进。可以用下面的形式。 select a.id1,a.id2,b.id2 from game_new a ,game_new_bak b where a.id1=b.id1(+) 所以就建议语句从原来的形式 SELECT A.CN,A.GRADE,A.RANK,A.SCORE,DECODE(SIGN (A.RANK-(NVL(B.RANK,-1))),1,2,-1,3,0,1), SYSDATE,(NVL(B.RANK,-1)),B.SIGN,B.FLAG,B.TAG,B.SCORE FROM ( SELECT * FROM GAME_VIP_NEW MINUS SELECT * FROM GAME_VIP_NEW_BAK ) A LEFT JOIN GAME_VIP_NEW_BAK B ON A.CN=B.CN 修改为: SELECT /*+parallel(4)*/ A.CN,A.GRADE,A.RANK,A.SCORE,DECODE(SIGN (A.RANK-(NVL(B.RANK,-1))),1,2,-1,3,0,1), SYSDATE,(NVL(B.RANK,-1)),B.SIGN,B.FLAG,B.TAG,B.SCORE FROM GAME_VIP_NEW a,cydba.GAME_VIP_NEW_BAK B where A.CN=B.CN(+) 考虑到执行的情况和资源情况,加了一个并行,可以在一定程度上缓解这个问题。 在本地的环境中进行了测试,发现几分钟就可以轻松搞定,做了基本的确认,就和开发进行了反馈,对线上的存储过程内容进行了修改。 这个问题的解决也就终于告一段落。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 杨建荣的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档