深度解析dba_segments和sys.seg$中的细节差异(下) (r5笔记第28天)

时间:2022-05-04
本文章向大家介绍深度解析dba_segments和sys.seg$中的细节差异(下) (r5笔记第28天),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

继续昨天的内容:深度解析dba_segments和sys.seg$中的细节差异(上) (r5笔记第27天) 我们已经根据dba_segments和sys.seg$的不同发现最后的差距有2T左右,已经定位到了dba_segments的一些细节信息,可以发现其实还是一个层级的调用关系。

我们把SYS_DBA_SEGS是一个处于中间层的角色,它的定义是3个union all,可以从定义中看到,差别主要还是segment_type的不同,我们采用逐个击破的方法,一个一个来看。 -->第一个子查询 select NVL(u.name, 'SYS'), sum(s.blocks) from sys.user$ u, sys.obj$ o, sys.ts$ ts, sys.sys_objects so, sys.seg$ s, sys.file$ f where s.file# = so.header_file and s.block# = so.header_block and s.ts# = so.ts_number and s.ts# = ts.ts# and o.obj# = so.object_id and o.owner# = u.user# (+) and s.type# = so.segment_type_id and o.type# = so.object_type_id and s.ts# = f.ts# and s.file# = f.relfile# and u.name='PRDAPPO' group by u.name NVL(U.NAME,'SYS') SUM(S.BLOCKS) ------------------------------ ------------- PRDAPPO 323983920 SQL> select 32398390*8192/1024/1024 size_MB from dual; SIZE_MB ---------- 253112.422 -->第二个子查询。 select NVL(u.name, 'SYS'),sum( s.blocks) from sys.user$ u, sys.ts$ ts, sys.undo$ un, sys.seg$ s, sys.file$ f where s.file# = un.file# and s.block# = un.block# and s.ts# = un.ts# and s.ts# = ts.ts# and s.user# = u.user# (+) and s.type# in (1, 10) and un.status$ != 1 and un.ts# = f.ts# and un.file# = f.relfile# and u.name='PRDAPPO' group by u.name no rows selected -->第三个子查询 select NVL(u.name, 'SYS'), sum( s.blocks) from sys.user$ u, sys.ts$ ts, sys.seg$ s, sys.file$ f where s.ts# = ts.ts# and s.user# = u.user# (+) and s.type# not in (1, 5, 6, 8, 10) and s.ts# = f.ts# and s.file# = f.relfile# and u.name='PRDAPPO' group by u.name no rows selected 所以看来主要的数据还是在第一个子查询,但是如果细想,有点奇怪啊,基表中查到的数据是2.6T左右。那剩下的2T还没有找到原因,到底差在哪了。 我们这个时候可以往回看,sys.seg$里的信息得到的是2.6T,dba_segments里面得到的信息是5T左右。那么唯一的差别就在于sys_dba_segs了,是不是这个中间表做了什么操作呢。 我们截取相关的字段查看一下。 select sum(decode(bitand(segment_flags, 131072), 131072, blocks, (decode(bitand(segment_flags,1),1, dbms_space_admin.segment_number_blocks(tablespace_id, relative_fno, header_block, segment_type_id, buffer_pool_id, segment_flags, segment_objd, blocks), blocks)))) from sys_dba_segs where owner='PRDAPPO' ; SUM(DECODE(BITAND(SEGMENT_FLAGS,131072),131072,BLOCKS,(DECODE(BITAND(SEGMENT_FLA -------------------------------------------------------------------------------- 607401104 这下数字就对上了,可以看到在统计过程中,做了大量的判断,可以从下面改动的语句中做一些基本的分析。 SQL> select sum(decode(bitand(segment_flags, 131072), 131072,blocks)) col1, sum(decode(bitand(segment_flags,1),1,dbms_space_admin.segment_number_blocks(tablespace_id, relative_fno, header_block, segment_type_id, buffer_pool_id, segment_flags, segment_objd, blocks))) col2 from sys_dba_segs where owner='PRDAPPO' group by segment_flags ; 12860336 12860336 4145504 209686704 210292912 385152992

可以从上面的语句看出,主要的差别数据都在dbms_space_admin.segment_number_blocks调用中产生差异。 对此,我们需要查看一下这个包中对应的代码,但是不幸的是这部分代码做了屏蔽,我们看看是怎么描述的。 function segment_number_blocks( header_tablespace_id in natural , header_relative_file in positive , header_block in positive , segment_type in positive , buffer_pool_id in natural , dictionary_flags in natural , data_object_id in number, dictionary_blocks in number ) return pls_integer; pragma RESTRICT_REFERENCES(segment_number_blocks,WNDS,WNPS,RNPS); -- -- Returns the number of blocks which belong to the segment. Will return -- NULL if segment has disappeared. IS NOT to be used for any other -- purposes but by the views which need it and are sure that there info -- is correct. Else internal errors will abound 我们继续来看一下,尽管没有代码可供参考,但是我们还是能够做些什么,至少我们可以定位到底是哪些segment在统计时出现了大的数据出入。 我们用下面的语句来看一下。 col segment_name format a30 col partition_name format a20 select t1.segment_name,t1.partition_name,t1.sum_blocks,t2.sum_blocks,(t1.sum_blocks-t2.sum_blocks)*8192/1024/1024 diff_size_MB from (select owner,segment_name,partition_name,sum(blocks) sum_blocks from dba_segments where owner='PRDAPPO' group by owner,segment_name,partition_name )t1, (select NVL(u.name, 'SYS')owner,o.name oname,o.subname,sum(s.blocks) sum_blocks from sys.user$ u, sys.obj$ o, sys.ts$ ts, sys.sys_objects so, sys.seg$ s, sys.file$ f where s.file# = so.header_file and s.block# = so.header_block and s.ts# = so.ts_number and s.ts# = ts.ts# and o.obj# = so.object_id and o.owner# = u.user# (+) and s.type# = so.segment_type_id and o.type# = so.object_type_id and s.ts# = f.ts# and s.file# = f.relfile# and u.name='PRDAPPO' group by u.name,o.name,o.subname)t2 where t1.owner=t2.owner and t1.segment_name=t2.oname and t1.partition_name=t2.subname and t1.sum_blocks-t2.sum_blocks>0 order by t1.sum_blocks-t2.sum_blocks desc 可以看到,对于不同的segment_type产生的数据差异。可以看到在分区表中还是存在着较大的出入,数据差别 779705M+697946M+445368 大约是1.9T左右,可见问题的定位找到了一些突破口。

SEGMENT_TYPE SUM_BLOCKS SUM_BLOCKS DIFF_SIZE_MB ------------------ ---------- ---------- ------------ TABLE PARTITION 292044544 192242304 779705 INDEX PARTITION 131229056 41891872 697946.75 LOB PARTITION 110592896 53585792 445368 INDEX 27807392 4629536 181077 TABLE 44770432 31578752 103060 LOBSEGMENT 5386880 220928 40359 LOBINDEX 14336 14336 0 通过上面的语句我们可以继续分析。为什么有些分区相关的段有较大的数据差异。 同时也在Metalink上查了一下,有一篇文章:Bug 12940620 Cached block/extent counts in SEG$ not updated after ADD extent 这个里面描述的是一个bug,是关于查询比较慢的问题,和目前的使用的场景有些类似,可以做进一步的关注。