暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

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

IT那活儿 2020-07-15
3760


前面看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审核平台进行监控告警。

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

最后修改时间:2020-07-15 11:19:31
文章转载自IT那活儿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论