oracle中12c比10g索引回表消耗增多的问题

问题是这样的:
在12c中,我们测试了2种情况:
第一种是加了hint,使得12c的执行计划和10g类似,只是由于12c的nlj_batching,多了一次nestloop。但是执行计划本质是相同的,都是索引S_CONTACT_X_U1返回表查询。
第二种是使用了10g的outline hint,OFE=10g的,执行计划完全一样。

但是我们发现,无论是在12c中的哪一种情况,驱动表S_SRV_REQ的索引PA_S_SRV_REQ_1_X的full index scan返回结果差异这么大?

 

12c-第一种情况:

12c-第二种情况:

10g数据库的情况:

###################################

另外,根据过滤条件,10g和12c返回结果也差不多。且消耗也差不多!

12c:

10g:

(1)首先,这个SQL逻辑有问题。可以见我附件10g.txt中的附件,有完整的sql文本

 


SQL的主要功能是分页,客户这里把rownum和order by写在一层关系中了。所以这个是错误的。

(2)就算是在逻辑错误,为什么10g跑快,A-rows小?
这是因为SQL语句中rownum<=10, 而10g的返回记录是10行,12c的返回记录只有4行。
在rownum<=10的情况下,10g扫描索引的时候,扫描了264行之后,已经够10行了,所以可以返回;而12c中扫描索引,只有4行,也就是说,从开头扫到结尾,扫描全部还没找齐10行。所以需要扫描整个索引。因此消耗就高了。
其实我将SQL语句改写成rownum<=4,这样也可以在3秒多返回记录了。或者我将SQL改成rownum<=8000,那么在10g中运行也很慢了。

 


(3)修正SQL逻辑后,客户的SQL还是跑的慢,15分钟,发现因为客户写的hint用到的索引不是最优执行计划,使用acct_open_dt这个字段的索引之后(或者不用指定,oracle自己的CBO会选择这个索引),还要把1/3移动到右边,结果不到1秒就出来了。(注,如果1/3不移动到右边,还是会很慢。)

在这个案例中,我们可以学到的知识点:
1. 要分析SQL语句的逻辑,不能光看执行计划
2. 要注意count stopkey和a-rows的值。不然会想不明白为什么在10g扫描了264行就停止了。
3. 对方说数据源是一样的,不能完全相信。上述例子就可以看到,同样语句实际数据源还是有差异的,一个返回10行一个返回4行,而这个原因导致执行效率差别很大。
4. 索引字段有运算关系,需要把运算放到右边。才能正常使用索引。

时间: 2025-01-02 19:32:43

oracle中12c比10g索引回表消耗增多的问题的相关文章

Oracle中创建用于测试的大表

个人实验的时候有时会用到一些大表,在此分享用dba_objects来创建测试大表的方法: 首先建立测试表 SYS@ORCL>create table test nologging as select rownum id,a.* from dba_objects a where 1=2; SYS@ORCL>declare l_cnt number; l_rows number:=&1; begin insert /*+ append */ into test select rownum,

Oracle中如何建立分区表及簇表

1.分区表:(>2G)对大表进行优化   (Range Partitioning,List PartitioningHash Partitioning,Composite Partitioning) --按range 建立分区表 1  create table sales_range 2  (salesman_id number(5), 3   salesman_name varchar2(30), 4   sales_amount number(10), 5   sales_date   da

oracle中变长数组varray,嵌套表,集合使用方法_oracle

创建变长数组类型 CREATE TYPE varray_type AS VARRAY(2) OF VARCHAR2(50); 这个变长数组最多可以容纳两个数据,数据的类型为 varchar2(50) 更改元素类型的大小或精度 可以更改变长数组类型和嵌套表类型 元素的大小. ALTER TYPE varray_type MODIFY ELEMENT TYPE varchar2(100) CASCADE; CASCADE选项吧更改传播到数据库中的以来对象.也可以用 INVALIDATE 选项使依赖对

Oracle中在pl/sql developer修改表的两种方式

一.方式一 select * from student for update student表需要操作人修改完commit之后才可以做其他的操作,否则该表会被锁住. 二.方式二 select t.*,t.rowid from student t 在pl/sql developer中右击某表,显示的就是该语句,这样做不会将该表锁住. 想修改某几个字段也没有问题select num,name,t.rowid from student t.

oracle中12C sysaux 异常恢复—ORA-01190错误恢复

有朋友请求支援,他们数据库由于file 3 大量坏块,然后直接使用rman 备份还原了file 3,但是在recover过程中发现归档丢失,而且整个库在丢失归档的scn之后,还做过resetlogs操作,导致现在整个库无法正常启动,报ORA-01190错误,希望帮忙把file 3 给online起来,整个库正常open[当然在丢失sysaux的情况下,数据库可以open起来,但是这种情况下,迁移数据比较麻烦] SQL> startup; ORACLE 例程已经启动.   Total System

Oracle中在pl/sql developer修改表的两种语句

一.方式一 select * from student for update student表需要操作人修改完commit之后才可以做其他的操作,否则该表会被锁住. 二.方式二 select t.*,t.rowid from student t 在pl/sql developer中右击某表,显示的就是该语句,这样做不会将该表锁住. 想修改某几个字段也没有问题select num,name,t.rowid from student t. 该种方式也可以修改多表联合查询的情况,现有table1和ta

Oracle中在pl/sql developer修改表的2种方法_oracle

一.方式一 select * from student for update student表需要操作人修改完commit之后才可以做其他的操作,否则该表会被锁住.   二.方式二 select t.*,t.rowid from student t 在pl/sql developer中右击某表,显示的就是该语句,这样做不会将该表锁住. 想修改某几个字段也没有问题select num,name,t.rowid from student t.

Oracle中捕获问题SQL解决CPU过渡消耗

oracle|解决|问题 本文通过实际业务系统中调整的一个案例,试图给出一个常见CPU消耗问题的一个诊断方法.大多数情况下,系统的性能问题都是由不良SQL代码引起的,那么作为DBA,怎样发现和解决这些SQL问题就显得尤为重要. 本案例平台为UNIX,所以不可避免的应用了一些Unix下常用的工具.如vmstat,top等. 本文适宜读者范围:中高级. 系统环境: OS: Solaris8 Oracle: 8.1.7.4 问题描述: 开发人员报告系统运行缓慢,已经影响业务系统正常使用.请求协助诊断.

oracle中not exists对外层查询的影响

又一个类似『12c比10g索引回表消耗增多的问题』的案例,同事在12c中跑的buffer get很高,但是在10g中跑的buffer很低.怀疑是不是12c的优化器有问题. 这个10g的环境和12c的环境,数据量大致一样,只是有很少部分的不同,但是就是这个很少部分不同,造成了not exists中的子查询返回不同的值,进而对外层查询产生不同的影响. 我们来用如下的代码模拟一下. 初始化数据: --10g drop table t1; drop table t2;   create table t1