love wife & love life —Roger的Oracle&MySQL技术博客

Phone:18180207355 提供专业Oracle&MySQL数据恢复、性能优化、迁移升级、紧急救援等服务

_optimizer_null_aware_antijoin引发的SQL性能问题

本站文章除注明转载外,均为本站原创: 转载自love wife & love life —Roger的Oracle&MySQL技术博客

本文链接地址: _optimizer_null_aware_antijoin引发的SQL性能问题

前几天某客户联系我说之前我们进行存储迁移的系统,有个SQL跑的极慢,根本跑不出来结果。通过VPN登录看了下,SQL确认跑的很慢。开始我很难理解,我们仅仅是进行了存储迁移,数据库基本上没动,为什么会有SQL性能问题呢?  我们先来看看有问题的SQL:

 

 

大家看该SQL的执行计划就知道,COST巨大无比,很显然这个SQL基本上是跑不动的。本人SQL优化比较弱,因此直接从原库进行对比,因此在原库跑了下SQL:

 

 

很明显,原库的执行计划要好的,通过对比执行计划,我们发现:性能较差的SQL的执行计划中,not in 被改写成了not exits,进行了一些filter操作。而性能较高的SQL的执行计划,则是选择了ANTI Join。
问题是原来为什么ok ?存储迁移之后就有问题了呢 ?第一感觉可能是调整了优化器参数,检查发现果然是:

通过将该参数改回默认值,测试一切正常。 这里我主要是通过SQLT来解决该SQL的性能问题,首先创建一个SQL profile,然后修改SQL profile的查询块信息即可,如下:

通过调整之后,SQL性能恢复正常。 虽然这是一个很常见的问题,然而我却是第一次在生产中碰见,下面进行一个简单的测试。
说明:测试脚本来自google。
—For 10.2.0.5

我们可以看到,仍然没有走办连接,还是走filter了,这里的类似nest loop,很明显效率很低,其原因是需要用T1表的每条记录去和T2 返回的结果集进行匹配。那么有没有办法让SQL走半连接呢 ? 肯定是可以的,如下:

我们可以看到,走半连接之后,效率明显要高的多。当然,这里不对t1表进行not null操作也可以进行优化。
—-for 11.2.0.2 test

实际上,通过我们测试可以发现,本质上应用SQL出问题,不是我们调整参数的问题,而是应用SQL写法不规范导致。或者说应用表结构设计存在缺陷导致。实际上该SQL,我们不需要调整隐含参数,通过对表的column 添加非空约束即可。

Leave a Reply

You must be logged in to post a comment.