• oracle视图V$BH && X$BH的使用列子


    1创建一个测试表,test,并且插入10000行数据;
        SQL>  create table test (id int);

        SQL> begin
          2  for i in 1..10000 loop
          3  insert into test values(i)
          4  end loop;
          5  end;
          6  /
        SQL> commit;

    2
    创建一个存储过程SHOW_SPACE

    create or replace procedure show_space

           ( p_segname in varchar2,

      p_owner   in varchar2 default user,

      p_type    in varchar2 default 'TABLE',

      p_partition in varchar2 default NULL )

    as

        l_total_blocks              number;

        l_total_bytes               number;

        l_unused_blocks             number;

        l_unused_bytes              number;

        l_LastUsedExtFileId         number;

        l_LastUsedExtBlockId        number;

        l_last_used_block           number;

        procedure p( p_label in varchar2, p_num in number )

        is

        begin

            dbms_output.put_line( rpad(p_label,40,'.') ||p_num );

        end;

    begin

        dbms_space.unused_space

        ( segment_owner     => p_owner,

          segment_name      => p_segname,

          segment_type      => p_type,

          partition_name    => p_partition,

          total_blocks      => l_total_blocks,

          total_bytes       => l_total_bytes,

          unused_blocks     => l_unused_blocks,

          unused_bytes      => l_unused_bytes,

          last_used_extent_file_id => l_LastUsedExtFileId,

          last_used_extent_block_id => l_LastUsedExtBlockId,

          last_used_block => l_last_used_block );

        p( 'Total Blocks', l_total_blocks );

        p( 'Total Bytes', l_total_bytes );

        p( 'Unused Blocks', l_unused_blocks );

        p( 'Unused Bytes', l_unused_bytes );

        p( 'Last Used Ext FileId', l_LastUsedExtFileId );

        p( 'Last Used Ext BlockId', l_LastUsedExtBlockId );

        p( 'Last Used Block', l_last_used_block );

    end;

    /

    3检查表test的空间使用情况:
        SQL> exec show_space('TEST');
        Total Blocks............................24
        Total Bytes.............................196608
        Unused Blocks...........................3
        Unused Bytes............................24576
        Last Used Ext FileId....................1
        Last Used Ext BlockId...................62177
        Last Used Block.........................5

        由上可知,该表test共占用了24个数据块,196608字节,文件ID为1. 其实这里也可以直接查询 dba_segments看到这些信息.   

    SQL> select f,b from (
      2  select dbms_rowid.rowid_relative_fno(rowid) f,
      3         dbms_rowid.rowid_block_number(rowid) b
      4  from test) group by f,b order by b;

             F          B
    ---------- ----------
             1      62162
             1      62163
             1      62164
             1      62165
             1      62166
             1      62167
             1      62168
             1      62169
             1      62170
             1      62171
             1      62172
             1      62173
             1      62174
             1      62175
             1      62176
             1      62177

    16 rows selected.
       
     由此可见,表test中的数据共占用了16个数据块,但是前面第三步中,发现该表占用了24个数据块。这是正常的,因为oracle本身会使用8个数据块来记录段头、位图块等额外的信息。我们现在只需要了解到,表test共占用了24个数据块,其中16个是数据,8个是表信息。

    5,检查x$bhv$bh的更新:
      SQL> select file#,dbablk,tch from x$bh where obj=
      2  (select data_object_id from dba_objects
      3  where owner='SYS'  and object_name='TEST')
      4  order by dbablk;

         FILE#     DBABLK        TCH
    ---------- ---------- ----------
             1      62161          6
             1      62162          3
             1      62163          3
             1      62164          3
             1      62165          3
             1      62166          3
             1      62167          3
             1      62168          3
             1      62169          3
             1      62170          3
             1      62171          3
             1      62172          3
             1      62173          3
             1      62174          3
             1      62175          3
             1      62176          3
             1      62177          3
             1      62178          3
             1      62179          3
             1      62180          3
             1      62181          3

    21 rows selected.

      SQL> select file#,block#,status from v$bh where objd=
      2  (select data_object_id from dba_objects
      3  where owner='SYS'  and object_name='TEST')
      4  order by block#;

         FILE#     BLOCK# STATUS
    ---------- ---------- -------
             1      62161 xcur
             1      62162 xcur
             1      62163 xcur
             1      62164 xcur
             1      62165 xcur
             1      62166 xcur
             1      62167 xcur
             1      62168 xcur
             1      62169 xcur
             1      62170 xcur
             1      62171 xcur
             1      62172 xcur
             1      62173 xcur
             1      62174 xcur
             1      62175 xcur
             1      62176 xcur
             1      62177 xcur
             1      62178 xcur
             1      62179 xcur
             1      62180 xcur
             1      62181 xcur

    21 rows selected.

        这里可以看到,在v$bh和x$bh中得到的数据块,是从62161~62181的21条记录,但是在第四步中,我们知道数据是占用了62162~62177的16个数据库,这里,62161数据块里面存放的是段头信息,可以通过如下命令进行验证:
      SQL> select header_file,header_block from dba_segments
      2  where owner='SYS' and segment_name='TEST';

        HEADER_FILE HEADER_BLOCK
        ----------- ------------
              1        62161

        在v$bh视图中,我们可以看到这21个数据块都是xcur状态,表示这些数据块都是排斥状态,正在被使用,该字段还有其他的类型,请参见数据块的状态类型

    oracle缓冲块(data block)状态类型

        oracle的缓冲块的管理机制一直没有正式的发布过,因此许多有经验的oracle工程师都是通过经验或者一下oracle文档中的注释来推断oracle的缓冲块的管理机制的。

        事实上,oralce使用v$bh视图来记录与数据缓冲(data buffer)相关的信息,它详细记录了数据缓冲中每一个数据块(data block)的状态信息。

        在v$bh视图中的status字段,记录了数据块的状态,在非OPS、非RAC这样的集群环境中,数据块的状态会是下列几种之一:xcur,cr,read,free,用户可以通过如下命令得到数据库的状态信息:
        SQL> select unique status from v$bh;

        其状态的意义分别是:

        xcur:(exclusive current)的意思,表示该数据块处于排外模式;
        cr:表示该数据块是一个克隆(clone)的数据库,可以执行共享的只读操作;
        free:表示这是一个限制的数据块,oracle现在没有使用它;
        read:表示该数据块正在从磁盘读取数据;
        write:表示数据库正在往磁盘写入数据;

        在数据库恢复过程中,该字段还有另外两个描述:mrec和irec:
        mrec:(media recovery)表示数据块处于介质恢复模式;
        irec:(instance recovery)表示数据块处于实例恢复模式;

        在RAC环境中,数据块还有另外一种模式:
        scur (shared current),表示该数据库正在和其他实例共享数据。
       

     

     

     


    6,清空数据缓存:
        SQL> alter system flush buffer_cache;
    (在Oracle9i里,Oracle提供了一个内部事件,用以强制刷新Buffer Cache,其语法为:

    alter session set events 'immediate trace name flush_cache level 1';

    或者:

    alter session set events = 'immediate trace name flush_cache';

    类似的也可以使用alter system系统级设置:

    alter system set events = 'immediate trace name flush_cache';

    在Oracle10g中,Oracle提供一个新的特性,可以通过如下命令刷新Buffer Cache:

    alter system flush buffer_cache;

     


    7,重新检查v$bhx$bh的内容:
      SQL> select file#,dbablk,tch from x$bh where  obj=
      2  (select data_object_id from dba_objects
      3  where owner='SYS'  and object_name='TEST')
      4  order by dbablk;

         FILE#     DBABLK        TCH
    ---------- ---------- ----------
             1      62161          0
             1      62162          0
             1      62163          0
             1      62164          0
             1      62165          0
             1      62166          0
             1      62167          0
             1      62168          0
             1      62169          0
             1      62170          0
             1      62171          0
             1      62172          0
             1      62173          0
             1      62174          0
             1      62175          0
             1      62176          0
             1      62177          0
             1      62178          0
             1      62179          0
             1      62180          0
             1      62181          0

    21 rows selected.

        SQL> select file#,block#,status from v$bh where objd=
      2  (select data_object_id from dba_objects
      3  where owner='SYS'  and object_name='TEST')
      4  order by block#;

         FILE#     BLOCK# STATUS
    ---------- ---------- -------
             1      62161 free
             1      62162 free
             1      62163 free
             1      62164 free
             1      62165 free
             1      62166 free
             1      62167 free
             1      62168 free
             1      62169 free
             1      62170 free
             1      62171 free
             1      62172 free
             1      62173 free
             1      62174 free
             1      62175 free
             1      62176 free
             1      62177 free
             1      62178 free
             1      62179 free
             1      62180 free
             1      62181 free

    21 rows selected.

        这时候我们可以看到,x$bh中的tch字段,已经由原来的3变成了0,同时v$bh视图的数据块状态也变成了free,但是记录的数据块并没有发生变化,还是在62161~62181这些数据块中,这就是说,虽然数据已经被写到了磁盘中,但是数据库记录的指针并没有清空,仅仅是其状态发生了改变。

    我们读取到了x$bh中的tch字段,该字段表示的该字段被读取/写入的次数,这个值在oracle的LRU算法中,是一个重要的参数,如果这个字段被访问,则该值就会增加
    tch(touch count) 是通过touch标记的方式在追踪热块.


    1,第一次查看TCH的值:
        1.1 获得表ID:
        SQL> select data_object_id from dba_objects
        2     where wner='SYS' and object_name='TEST';

        DATA_OBJECT_ID
        --------------
                 60629
        
        1.2 获得表所占用的数据库ID:
        SQL> select unique dbablk from x$bh where bj=60629;
        
        1.3 获得该表中,62191数据库的tch值:
        SQL> select tch from x$bh where bj=60629 and dbablk=62191;

               TCH
        ----------
                 2

    2,再次读入表test;
        SQL> select count(*) from test;

          COUNT(*)
        ----------
             20000

    3,重复1.3操作,再次检测tch值:
        SQL> select tch from x$bh where bj=60629 and dbablk=62191;

               TCH
        ----------
                 3

        用户可以继续试验,TCH会继续增长。由此可见,用户可以通过x$bh,获得系统中访问量比较大的字段以及其所在数据库,进一步优化存储的安排,提高系统性能。

    下面的script可以列出top 10的热点块对象
    select /*+rule*/ owner,object_name from dba_objects
    where data_object_id in
    (select obj from (select obj from x$bh order by tch desc) where rownum < 11);

    关于热块的文章:

    http://www.cnblogs.com/princessd8251/articles/3876834.html

  • 相关阅读:
    【codeforces 411B】Multi-core Processor
    【codeforces 314C】Sereja and Subsequences
    【hdu 1890】Robotic Sort
    【图灵杯 A】谷神的赌博游戏
    【图灵杯 J】简单的变位词
    【图灵杯 F】一道简单的递推题(矩阵快速幂,乘法模板)
    【图灵杯 E也即POJ 3368】简单的RMQ
    【codeforces 496E】Distributing Parts
    【codeforces 553C】Love Triangles
    Diffie-Hellman Key Exchange – A Non-Mathematician’s Explanation
  • 原文地址:https://www.cnblogs.com/princessd8251/p/3877047.html
Copyright © 2020-2023  润新知