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

SQL性能优化实例解析(4)

甲骨文云技术 2020-08-24
2167

执行计划97行的SQL,必须要上下滚动屏幕才能看到完整的执行计划,要怎么优化?

喜欢挑战的你,现在就去文末拿到SQL Monitor Report,然后自己看看问题在哪里吧?
第一感觉,是不是这个SQL Monitor Report怎么和之前的长的都不一样?嗯,与时俱进么,老版的SQL Monitor Report都是基于Flash的,19c之后默认的SQL Monitor Report就都是非Flash版的,就是长的如本文例子中的这样事儿的,参见下图:

从上图中可以看到,这条SQL执行时间是20.6分钟,I/O Bytes是1.5TB,请问此刻你的想法?

你有没有想,1.5TB I/O 20.6分钟就完成了还想闹哪样?怎么说呢,这条SQL,可是在Exadata上跑的,执行计划里面写着呢,TABLE ACCESS STORAGE FULL。如果SQL Monitor Report此刻已经在你手边,你可以把鼠标放在右上角的I/O Bytes上,就可以看到,Read I/O是890.8GB,WriteI/O是620.4GB,随便翻翻Exadata的data sheet,1.5TB I/O,N秒就能完成,用I/O量太大所以SQL跑的慢这个蹩脚理由,只能糊弄外行呢。
想要优化这条SQL,入手点在哪里?
对的,最右边,Wait Activity%那一列,表示的是执行每一步的时候,对应的数据库里面的活动(Activity)的样本数,颜色条最长的步骤,意味着执行那一步花的时间最长,就是入手点。如下图:

其实是如上面的两图啦,即使是截屏两次,也仅仅是97行执行计划中的一部分。
入手点的两行,是HASH GROUP BY,分别使用了100多G的TEMP。SQL Monitor Report的Activity Tab和Metrics Tab也述说着同样的问题:

HASH GROUP BY,使用大量的TEMP,只能是问题的表象,根本原因是什么,肯定还是要看具体情况。
HASH GROUP BY是将STORE_RETURNS表和STORE_SALES表的join结果进行HASH GROUP BY。
SQL Monitor Report的第30行,HASH JOIN的结果,优化器估计(Est. Rows列)是29M行,实际(Rows列)是2880M行,相差了大约100倍。
再看SQL Monitor Report的第35行和第39行,优化器对于STORE_RETURNS表和STORE_SALES 表的估计,都是非常准确的。

那么为什么对JOIN的结果估计会相差100倍之多呢?

那肯定是要看看JOIN KEY的情况。非Flash版SQL Monitor Report直接将Access Predicates和Other Information显示在了Plan Statistics的Information列里面,非常方便。点击入手点后面的HASH JOIN步骤的Access Predicate(下图中的望远镜旁边的小图标),就可以看到JOIN KEY是

"SS_ITEM_SK"="SR_ITEM_SK"AND "SR_TICKET_NUMBER"="SS_TICKET_NUMBER"

也就是说,JOIN KEY是两列。那么,如果JOIN KEY这两列之间有相关性的话,优化器对于JOIN的结果集估计会偏小,在我们这个例子里面是偏小了大概100倍。这个错误的估计又进一步导致了优化器选择在join STORE_SALES和STORE_RETURNS后先做Group By,再将结果和DATE_DIM表Join。

事实上,SQL Monitor Report里面第二第三花时间的地方,也是类似的情况,如下面两图:

......

在确认了JOIN KEY的两列之间有相关性,导致优化器对JOIN结果集大小估计错了大概100倍,是问题的根本原因之后,解决方案就容易了。
分别在表STORE_SALES(SS_ITEM_SK,SS_TICKET_NUMBER)和表STORE_RETURNS (SR_ITEM_SK, SR_TICKET_NUMBER)的两个列上创建扩展统计信息。
实施解决方案后,Join顺序发生改变,优化器选择先join DATE_DIM和STORE_SALES,再将结果和STORE_RETURNS表join。最后再在更小的结果集上做Group By。

另外两处问题同理,应用类似的解决方案。最终只用了不到70GB的TEMP,只做了494.9GB I/O,就完成了SQL的执行,执行时间7.5分钟
总结一下
问题SQL,执行时间20.6分钟
  • 拿到问题SQL的SQL MonitorReport (数据库自带

  • 检查最右边的Activity%列,找出颜色条最长的那一行,做为入手点

  • 检查入手点那一行的具体情况

  • 如果入手点那一行是HASH GROUP BY,要看是对哪个Row Source进行HASH GROUP BY,在本文例子中,是对HASH JOIN的结果进行HASH GROUP BY

  • Estimated Rows(估计行数)和Actual Rows(实际行数)的对比是很重要的信息,如果估计有数量级级别的错误,大概率会导致不好的执行计划。本文例子中,HASH JOIN的两个表的估计都非常准确,但是HASH JOIN的结果集大小估计差了大概100倍,导致HASH GROUP BY步骤使用了300多G的TEMP,SQL执行性能差

  • 19c的SQL Monitor Report里面,Access Predicate在Plan Statistics的Information列,可以点击Information列里面的望远镜旁边的小图标检查Access Predicate,本文例子中就通过点击望远镜旁边的小图标确认了JOIN KEY是什么

  • 针对问题根源,实施在JOIN的两个表上分别对JOIN KEY的两列收集扩展统计信息的解决方案,SQL执行时间变为7.5分钟

这个系列的文章,这是第四篇。前面三篇里面的执行计划,基本上一屏可以显示的下,是希望跟大家分享我们分析问题的思路和方法,同时也让大家对SQL Monitor Report这个神器有个感性的认识。

这一篇的执行计划,97行,是一个很复杂的SQL。我们希望通过这一篇,以及后面一篇的例子,让大家更深刻的理解为什么我们说SQL MonitorReport是神器,97行的执行计划,哪怕你对你的系统和SQL再熟悉,如果没有SQL Monitor Report这样的神器里面提供的这些信息,你要怎样定位入手点,怎样去进行你的SQL优化呢?

使用SQL Monitor Report神器,进行以数据为依据的分析和诊断,节省时间效果好,使用Oracle数据库的专享福利。既然用了高大上的数据库,自带的高大上神器为啥不用起来呢~~

更多SQL性能优化实例解析,欢迎在哔哩哔哩(app或微信小程序)上搜索“Oracle公益课堂”,就可以看到视频啦 -“RWP大开眼界系列-SQL MonitorReport分析”

点击下方阅读原文获取文中提到的报告文档
扫描下方QR Code即刻预约ADW演示

编辑:范宏伟

文章转载自甲骨文云技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论