一条update语句的优化探索

今天经开发同学反馈,发现有一些update语句阻塞了部分业务流程,为什么说一些而不是一条,是因为这些update语句都在一个存储过程中,语句结构相仿,真有一种一荣俱荣,一损俱损的感觉。而比较纠结的是这样的update语句有差不多10个。从我收到反馈到观察分析,里面的第一条update语句运行了近5个小时,还没有完成,从SQL Monitor的报告来看,似乎进度甚微,按照这个进度,这些语句的执行时间会非常惊人。

我先拿到了一个初步的报告。

概览信息如下:

这条语句从生成的执行计划来看,简直完美,但是执行时间却差强人意,所以由此来看是执行计划出现了巨大的偏差。这个时候SQL Monitor是一个利器,可以真实还原问题时段的执行计划情况。


如果看上面的执行计划,其实看起来消耗也不大,好像都走了索引,在这样的一个评估值的情况下,可见数据集的变化不大。而问题就在于右边的部分。


红色的小框处标出的信息,可以看出实际得到的结果集非常惊人,结果集行数都是4G,这是一个什么级别的概念。所以这个语句的瓶颈就在这个地方。

我们来看看语句:

这个语句看起来还是比较复杂的,两个相关的表都是千万级别,红色的部分就是涉及的关键部分,都涉及到vip_recharge_log这张大表。从执行计划来看是在这里出了问题。

vip_recharge_log对应的索引信息如下:


可以看出这个语句是根据时间字段来做的数据过滤。这种方式为什么性能低效呢,和between的部分有着重大的关系。

时间跨度有多大呢,可以通过如下的表达式来得到一个时间范围。

这是取近半年的数据结果,对于一个OLTP的千万级表来说,全表扫描的代价其实要更低一些。这样SQL在执行的过程中先根据时间字段来过滤得到一个极大的结果集,然后在这个基础上去根据id得到一个极小的结果集。这种方式简直是百害而无一利。如果根据id得到一些客户的信息,因为本身结果集就小很多,在这个基础上再根据时间来过滤,那效率会大大提高,在目前的这个场景中可以看见明显的性能问题。

所以初步的评估就是重构索引。目前的索引是根据时间字段或者根据id来创建索引,其实可以考虑复合索引,根据id,时间字段来过滤数据,成本相对要低很多。所以考虑创建一个新的索引

CREATE INDEX "IDX_VIP_RECHARGE_MIX" ON "VIP_RECHARGE_LOG"
       (CN,CHARGE_DATE )  ;

这样数据过滤的效果就会好很多。这个瓶颈能够化解了,其它的几个问题也就引刃而解。

所以在这种场景下,不修改SQL语句,调整索引就预估达到极大的性能提升。而对于此还是需要很谨慎的,我复制了表中的数据,在另外的环境进行了快速的复现,执行计划的效率大大提高。在这个基础上,考虑添加了并行,虽然会消耗服务器的资源,但是能够极大提高效率,这些付出也是合理的。在这些简单调整之后,再次测试运行语句,1分半钟就能够顺利完成。

时间: 2024-07-30 07:57:18

一条update语句的优化探索的相关文章

[20150715]一条sql语句的优化.txt

[20150715]一条sql语句的优化.txt --生产系统发现一条语句. update presc_check t set t.diagnosis=replace(t.diagnosis,',慢性病drugs','') --第1眼看到的感觉真的很想骂人,什么能没有where条件呢? --我把这个表拷贝过来.这个表占用1G多1点,在测试环境执行看看: -- copy from system/xxxx@ip:1521/tyt create presc_check using select * f

[20140210]一条sql语句的优化(11g).txt

  [20140210]一条sql语句的优化(11g).txt 今天下午看生产系统数据库,无意中发现一个错误,同时优化也有点小问题,写一个测试脚本. 1.建立测试环境: SCOTT@test> @ver BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 -

sql server-求助:sqlserver一条sql语句的优化 是否需要索引 建立什么样的索引合适

问题描述 求助:sqlserver一条sql语句的优化 是否需要索引 建立什么样的索引合适 1C select COUNT(*) total from (select distinct(device_token) from MDM_POLICY_UPDATE where len(device_token)=64 and SW='crmi_poly') a 解决方案 我觉得直接可以用count(device_token) 然后直接groupby device个人感觉最拖后腿的应该是len()这个函

请教大神一条sql语句的优化

问题描述 请教大神一条sql语句的优化 表名pm,以temp分组,count两个信息,一个是全部个数,另一个是status为1 id temp status 1 1 0 2 1 1 3 2 0 4 2 1 5 2 1 select total.temp ,used.c1,total.c2 from (select temp,count(1) c1 from pm group by temp ) total left join (select temp,count(1) c2 from pm wh

[20151209]一条sql语句的优化(续).txt

[20151209]一条sql语句的优化(续).txt http://blog.itpub.net/267265/viewspace-1852195/ --上次提到其中1条sql语句: 1.环境: SYSTEM@192.168.99.105:1521/dbcn> @ver1 PORT_STRING                    VERSION        BANNER ------------------------------ -------------- -------------

[20130319]一条sql语句的优化.txt

[20130319]一条sql语句的优化.txt 生产系统,遇到这样一条语句:SELECT MAX (LENGTH (pe_id)) FROM pe_master_index WHERE SUBSTR (pe_id, 1, 2) = 'TJ'; --真不知道开发人员如何想的,写出这样的语句.字段pe_id是主键.--数据库版本 SQL> select * from v$version where rownum BANNER                                     

[20131025]一条sql语句的优化.txt

[20131025]一条sql语句的优化.txt 最近在优化一条sql语句,做一个测试例子测试看看.遇到一些问题记录一下: 1.建立环境: SCOTT@test> @ver BANNER -------------------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Productio

分享几条sql语句命令优化技巧

1.应用程序中,保证在实现功能的基础上,尽量减少对数据库的访问次数:通过 搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担:能够分 开的操作尽量分开处理,提高每次的响应速度:在数据窗口使用SQL时,尽量把使 用的索引放在选择的首列:算法的结构尽量简单:在查询时,不要过多地使用通配 符如SELECT * FROM T1语句,要用到几列就选择几列如:SELECT COL1,COL2 FROM T1:在可能的情况下尽量限制尽量结果集行数如:SELECT TOP 300 COL1,COL

力荐:一条update语句引发的“血案”

有一次得到应用同学的反馈,有一个前端应用登录很慢,已经开始影响业务登录了,稍后DBA介入,发现是由于CPU使用率过高导致,为了能够缓解问题和进一步分析,做了一些改进措施,最后问题得到了化解,但是对于这个问题后续也进行了更多的分析,也算是事后诸葛亮吧.   整个分享的思路如下: 问题背景 提出疑问 问题的对比测试 问题的验证 问题总结      问题背景     查看慢日志的情况如下:      两个查询的统计信息如下,可以看到平均执行时间竟然都在40s左右.     涉及的SQL语句如下,这个也