not exists对外层查询的影响

又一个类似『12c比10g索引回表消耗增多的问题』的案例,同事在12c中跑的buffer get很高,但是在10g中跑的buffer很低。怀疑是不是12c的优化器有问题。

这个10g的环境和12c的环境,数据量大致一样,只是有很少部分的不同,但是就是这个很少部分不同,造成了not exists中的子查询返回不同的值,进而对外层查询产生不同的影响。

我们来用如下的代码模拟一下。

我们看到,12c的数据和10g只是有很少的差别,t1表12c和10g都一样,t2表在12c只是少了一行数据。

我们将要执行的sql语句是:

我们先来看执行情况的差距,10g的bufferget小,12c多:

可以看到第23,24行,在10g中运行时,buffers是0,而在12c中,即78,79行,buffer是2083+6496。

也就是说在10g中,外层查询不进行t1和t2的扫描,直接返回结果了,而在12c中,外层查询还要进行t1表和t2表层扫描才返回结果。

这其实不是10g和12c的差别,而是not exists的返回数据对外层的影响。子查询要返回0行记录,才满足not exist的条件,从而返回外层查询结果。

在10g中,子查询返回了一行记录

不满足not exists(即0行才满足),所以,也就不用在外层继续查询了。直接返回记录0行。

在12c中,子查询返回0行记录,满足not exist的条件,所以还需要在外层查询中继续查询。

正是这一行记录的差异,导致了not exists对外层查询的影响。进而导致整个sql的buffer get的差异。

反证这个结果,我只要在12c中,运行子查询结果返回大于0行的,不满足not exists,也应该不会去外层查询了。见下:

可以看到第38,39行的buffer为0.

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据