资讯专栏INFORMATION COLUMN

性能优化之日期字段索引引发的血案一例

IT那活儿 / 2284人阅读
性能优化之日期字段索引引发的血案一例


前面看IT那活儿上不少兄弟都发表了文章,作为新四有好青年,咱也来凑凑热闹,毕竟会下蛋的鸡(总结提炼输出),才不是肉食鸡,才是飞机中的歼21。今天和大家来分享一个日期字段索引引发的血案及分析过程。

先给出今天的主角SQL语句:

咱先来掐指一算,分析下SQL语句的结构。此语句一打眼就是个统计语句,查询包括两张表,是一个正常的表等值关联的查询语句。


走过路过,但别错过的看看这个执行计划是否最优?

通过仔细查看发现如上执行计划是错误的。简单啰嗦一下执行计划。首先通过T1表的DATE字段选择过滤出结果集,在将表T通过CUSTMGR字段选择出结果集,再将两个查询的结果集通过NESTLOOP方式返回数据。正常情况下如果连接条件不是通过函数进行转换且CUST_ID上有索引的话,会通过索引CUST_ID进行NESTLOOP 返回结果。

那么我们怎么知道选择这种执行计划时不正确的呢?因为比之前正确的执行计划消耗更高。什么?我怎么知道的消耗更高?往下看就知道了嘛。


通过历史视图查询对应SQL_ID执行历史:

通过上面的查询结果,我们可以发现在3:30 ,出现了错误的执行计划。那么问题就来了,为什么会有错误的执行计划,为什么在10号发生?

我们可以推断此SQL是在每天3:30的时候进行定时执行,且10号前执行效率很高,所有2500次的执行均在秒内时间就完成了。但在10号后,由于错误执行计划出现,导致SQL执行时间变长,2500次的执行不能在规定时间内跑完,导致sql取数拖到了半天,占用白天的资源,进而影响正常的白天业务。

那么为什么会发生这样的情况呢?我们通过10053来仔细在查看一下:


错误执行计划的10053trace:

可以看到提示:Usingprorated density: 0.000001 of col #9 as selectvity ofout-of-range/non-existent value pred

这个提示说明出现了越界现象。当日期判断的范围超出了统计信息记录的最大值和最小值的范围,CBO无法计算选择率,得出错误的结果集,此时通过估计值进行选择,当评估的值与实际情况差别很大时,就会出现选择偏差。


查看表上日期字段的统计值

我们看到记录的最大日志是07-10,在与SQL语句SERVICEDATE>= (SYSDATE -30)执行计划出错的日期进行比较,发现8月10号-30天正好超过了记录的最大日期值。这就是执行计划变化发生在8月10日的罪魁祸首。


现在咱改写一下SQL语句,再看一下执行计划

执行计划已正确。


看一下对应的10053trace信息
很明显与之前错误执行计划trace信息不同,得到的COST和结果集大小不同。

我们通过上面的分析知道了问题出现的原因,处理方法也很简单:
  • 1. 收集表上统计信息

  • 2. 固定SQL的执行计划

  • 3. 创建组合索引,CUSTMGR+时间

  • 3.2 监控执行计划的变化

数据是千变万化的,作为一个老司机,我们多伸一下手顺带考虑通过编写监控脚本来预防问题的后续发生,发生时第一时间知晓及介入。


脚本的实现思路:
  • 1. 监控系统中出现SQL_ID和PLAN_HASH_VALUE,1:N的情况,过滤掉OBJECT_STATUS失效的对象,正常一个SQL_ID与一个当前真正使用的PLAN_HASH_VALUE对应,比较执行时间进行报警。

  • 2. 比较SQL_ID-PLAN_HASH_VALUE在历史中是否出现过,比较执行时间进行报警。

  • 3. 使用SQL审核平台进行监控告警。

好了,本新四有好青年的首次春宫秀到此结束,咱们下回再见。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/130212.html

相关文章

  • 空数组返回true引发血案

    摘要:但是在这个判断的情况下,则会很神奇的发现打印出来了,说明此时为,为什么呢因为这里执行了一个对象到布尔值的转换故返回。     之前做项目的时候,总会处理各式各样的数据,来进行绘图。但是当后台返回一个空数组的时候,页面中并不会显示没有数据的图。代码如下: var arr = [] if(arr){console.log(124)}else{console.log(无数据)} 我明明判断了...

    piglei 评论0 收藏0
  • 在PHP应用程序开发中不正当使用mail()函数引发血案

    摘要:在我们向厂商提交漏洞,发布了相关的漏洞分析文章后,由于内联函数导致的类似安全问题在其他的应用程序中陆续曝出。浅析的函数自带了一个内联函数用于在应用程序中发送电子邮件。 前言 在我们 挖掘PHP应用程序漏洞 的过程中,我们向著名的Webmail服务提供商 Roundcube 提交了一个远程命令执行漏洞( CVE-2016-9920 )。该漏洞允许攻击者通过利用Roundcube接口发送一...

    Galence 评论0 收藏0
  • 增量部署class文件引发血案

    摘要:背景项目中通过远程调用服务框架调用了许多其它的服务其中有一个服务需要升级其升级不是版本上的升级而是整个服务重新取了一个名字使用的也是全新的包但是调用的方法没有改变因此在升级时只是在调用服务类中修改了调用地址和调用返回实体由改为该中返回该调用 背景 项目中通过远程调用服务框架调用了许多其它的服务,其中有一个服务wx/subscribe/contract/CircleService 需要升...

    lolomaco 评论0 收藏0
  • 记一次Content-Length引发血案

    摘要:除非使用了分块编码,否则首部就是带有实体主体的报文必须使用的。 背景 新项目上线, 发现一个奇怪的BUG, 请求接口有很小的概率返回400 Bad Request,拿到日志记录的请求的参数于POSTMAN中测试请求接口, 发现能够正常响应. 排查过程 首先服务器能够正常响应400 Bad Request, 排除接口故障问题. 对比日志过程中发现 { hello:world ...

    thekingisalwaysluc 评论0 收藏0

发表评论

0条评论

IT那活儿

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<