zoukankan      html  css  js  c++  java
  • 【Oracle】表碎片重用规则

    看完该篇文章你可以了解如下问题:表碎片是如何产生的,这些碎片能否重用?

    数据库版本如下:

    SYS@zkm> select banner from v$version where rownum=1;
    
    BANNER
    --------------------------------------------------------------------------------
    Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
    

    创建一张空表TT,由于是sys用户的表,不会延迟段创建。
    因此可以看到区信息能够立刻查出来。

    SYS@zkm> create table tt (id int,name varchar2(2000)) tablespace users;
    
    Table created.
    
    SYS@zkm> select extent_id,file_id,block_id,bytes,blocks from dba_extents where segment_name='TT' and owner='SYS';
    
     EXTENT_ID    FILE_ID   BLOCK_ID      BYTES     BLOCKS
    ---------- ---------- ---------- ---------- ----------
             0          4       1960      65536          8
    

    查看段头块,一般段头块是第一个L3块。

    SYS@zkm> select HEADER_FILE,HEADER_BLOCK from dba_segments where OWNER='SYS' and SEGMENT_NAME='TT';
    
    HEADER_FILE HEADER_BLOCK
    ----------- ------------
              4         1962
    

    查找L3块的目的是找出0号区能够存放数据的块。
    dump出L3块截取部分数据如下。

    SYS@zkm> select value from v$diag_info where name like '%De%';
    
    VALUE
    --------------------------------------------------------------------------------
    /u01/app/oracle/diag/rdbms/zkm/zkm/trace/zkm_ora_2568.trc
    
    SYS@zkm> alter system dump datafile 4 block 1962; 
    
    System altered.
    
    
      Extent Control Header
      -----------------------------------------------------------------
      Extent Header:: spare1: 0      spare2: 0      #extents: 1      #blocks: 8
                      last map  0x00000000  #maps: 0      offset: 2716
          Highwater::  0x010007ab  ext#: 0      blk#: 3      ext size: 8
      #blocks in seg. hdr's freelists: 0
      #blocks below: 0
      mapblk  0x00000000  offset: 0
                       Unlocked
      --------------------------------------------------------
      Low HighWater Mark :
          Highwater::  0x010007ab  ext#: 0      blk#: 3      ext size: 8
      #blocks in seg. hdr's freelists: 0
      #blocks below: 0
      mapblk  0x00000000  offset: 0
      Level 1 BMB for High HWM block: 0x010007a8
      Level 1 BMB for Low HWM block: 0x010007a8
      --------------------------------------------------------
      Segment Type: 1 nl2: 1      blksz: 8192   fbsz: 0
      L2 Array start offset:  0x00001434
      First Level 3 BMB:  0x00000000
      L2 Hint for inserts:  0x010007a9
      Last Level 1 BMB:  0x010007a8
      Last Level II BMB:  0x010007a9
      Last Level III BMB:  0x00000000
         Map Header:: next  0x00000000  #extents: 1    obj#: 89302  flag: 0x10000000
      Inc # 0
      Extent Map
      -----------------------------------------------------------------
       0x010007a8  length: 8
      
        Auxillary Map
      --------------------------------------------------------
       Extent 0     :  L1 dba:  0x010007a8 Data dba:  0x010007ab
      --------------------------------------------------------
    
       Second Level Bitmap block DBAs
       --------------------------------------------------------
       DBA 1:   0x010007a9
    

    综合以上信息可以得到:

       区0的范围是:	
       				1960	L1块
    				1961	L2块
    				1962	L3块
    				1963	第一个存放数据的数据块
    				1964	第二个存放数据的数据块
    				1965	第三个存放数据的数据块
    				1966	第四个存放数据的数据块
    				1967	第五个存放数据的数据块
    							
       高水位线标志块:1963
    

    插入一行会话并回滚。

    SYS@zkm> insert into tt values(1,rpad('a',1800,'+'));
    
    1 row created.
    
    SYS@zkm> alter system flush buffer_cache;  --清空buffer cache,不然L3块中的高水位线标志点不会立刻刷新。
    
    System altered.
    
    SYS@zkm> rollback;
    
    Rollback complete.
    
    此时dump L3块可以看到高水位点变为1968号块,过程省略。
    

    以下每四条记录放在一个块中。

    SYS@zkm> insert into tt values(5,rpad('e',1804,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> commit;
    
    Commit complete.
    
    SYS@zkm> insert into tt values(5,rpad('e',1804,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> commit;
    
    Commit complete.
    
    SYS@zkm> insert into tt values(5,rpad('e',1804,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> commit;
    
    Commit complete.
    
    SYS@zkm> insert into tt values(5,rpad('e',1804,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> commit;
    
    Commit complete.
    
    SYS@zkm> insert into tt values(5,rpad('e',1804,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> commit;
    
    Commit complete.
    
    SYS@zkm> select id,substr(name,1,1),rowid,dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) block#,dbms_rowid.rowid_row_number(rowid) row# from tt;
    
            ID SUBS ROWID                   FILE#     BLOCK#       ROW#
    ---------- ---- ------------------ ---------- ---------- ----------
             5 e    AAAVzuAAEAAAAerAAA          4       1963          0
             5 e    AAAVzuAAEAAAAerAAB          4       1963          1
             5 e    AAAVzuAAEAAAAerAAC          4       1963          2
             5 e    AAAVzuAAEAAAAerAAD          4       1963          3
             5 e    AAAVzuAAEAAAAesAAA          4       1964          0
             5 e    AAAVzuAAEAAAAesAAB          4       1964          1
             5 e    AAAVzuAAEAAAAesAAC          4       1964          2
             5 e    AAAVzuAAEAAAAesAAD          4       1964          3
             5 e    AAAVzuAAEAAAAetAAA          4       1965          0
             5 e    AAAVzuAAEAAAAetAAB          4       1965          1
             5 e    AAAVzuAAEAAAAetAAC          4       1965          2
    
            ID SUBS ROWID                   FILE#     BLOCK#       ROW#
    ---------- ---- ------------------ ---------- ---------- ----------
             5 e    AAAVzuAAEAAAAetAAD          4       1965          3
             5 e    AAAVzuAAEAAAAeuAAA          4       1966          0
             5 e    AAAVzuAAEAAAAeuAAB          4       1966          1
             5 e    AAAVzuAAEAAAAeuAAC          4       1966          2
             5 e    AAAVzuAAEAAAAeuAAD          4       1966          3
             5 e    AAAVzuAAEAAAAevAAA          4       1967          0
             5 e    AAAVzuAAEAAAAevAAB          4       1967          1
             5 e    AAAVzuAAEAAAAevAAC          4       1967          2
             5 e    AAAVzuAAEAAAAevAAD          4       1967          3
    
    20 rows selected.
    

    可以看到高水位线1968以下的块(1963-1967)都被用完。测试下删除某一行,提交后在新建会话插入新的一行,看是否会填补到被删除行的位置。

    比如删除1966号块rowid为AAAVzuAAEAAAAeuAAB的块。

    会话1:
    SYS@zkm> delete from tt where rowid='AAAVzuAAEAAAAeuAAB';
    
    1 row deleted.
    
    SYS@zkm> commit;
    
    Commit complete.		 
    		 
    会话2:
    SYS@zkm> insert into tt values(5,rpad('e',1805,'+'));
    
    1 row created.
    
    SYS@zkm> commit;
    
    Commit complete.
    
    SYS@zkm> select id,substr(name,1,1),rowid,dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) block#,dbms_rowid.rowid_row_number(rowid) row# from tt;
    
            ID SUBS ROWID                   FILE#     BLOCK#       ROW#
    ---------- ---- ------------------ ---------- ---------- ----------
             5 e    AAAVzuAAEAAAAerAAA          4       1963          0
             5 e    AAAVzuAAEAAAAerAAB          4       1963          1
             5 e    AAAVzuAAEAAAAerAAC          4       1963          2
             5 e    AAAVzuAAEAAAAerAAD          4       1963          3
             5 e    AAAVzuAAEAAAAesAAA          4       1964          0
             5 e    AAAVzuAAEAAAAesAAB          4       1964          1
             5 e    AAAVzuAAEAAAAesAAC          4       1964          2
             5 e    AAAVzuAAEAAAAesAAD          4       1964          3
             5 e    AAAVzuAAEAAAAetAAA          4       1965          0
             5 e    AAAVzuAAEAAAAetAAB          4       1965          1
             5 e    AAAVzuAAEAAAAetAAC          4       1965          2
    
            ID SUBS ROWID                   FILE#     BLOCK#       ROW#
    ---------- ---- ------------------ ---------- ---------- ----------
             5 e    AAAVzuAAEAAAAetAAD          4       1965          3
             5 e    AAAVzuAAEAAAAeuAAA          4       1966          0
             5 e    AAAVzuAAEAAAAeuAAB          4       1966          1
             5 e    AAAVzuAAEAAAAeuAAC          4       1966          2
             5 e    AAAVzuAAEAAAAeuAAD          4       1966          3
             5 e    AAAVzuAAEAAAAevAAA          4       1967          0
             5 e    AAAVzuAAEAAAAevAAB          4       1967          1
             5 e    AAAVzuAAEAAAAevAAC          4       1967          2
             5 e    AAAVzuAAEAAAAevAAD          4       1967          3
    
    20 rows selected.
    

    可以看到高水位线以下有块能够容纳新行的话,会按照assm规则去选择这些块并插入数据(排除append)。在L1块中记录了所属数据块的存储状态,比如"0-25% free"或者full等。当然有不是full的情况下不代表可以insert进数据。比如0-25% free的时候,一行数据还是放不下的话会更新为full并且另找新的可以容纳下这一行数据的数据块。

    那么如果高水位线以下存在块可以容纳插入的行,碎片又是如何产生的呢?
    我们说频繁的dml会让表产生碎片,比如频繁insert会导致申请新区,提高高水位线,而后有频繁的delete使得空间空闲空间变得零碎,从而产生碎片。在insert是用append形式的时候,碎片问题会变得更严重。旧空间还未满,又申请新的空间。

  • 相关阅读:
    显示和隐藏一个div的问题
    javascript高级程序设计笔记-第八章(BOM)
    javascript高级程序设计笔记-第七章(函数表达式)
    javascript高级程序设计笔记-第六章(面向对象编程)
    javascript高级程序设计笔记-第五章(引用类型)
    javascript高级程序设计笔记-第四章(变量、作用域)
    javascript高级程序设计笔记-第三章(基本概念)
    css设计指南-笔记7
    CocoaPods 1.1.0上传遇到swift问题
    Attribute富文本使用方法
  • 原文地址:https://www.cnblogs.com/PiscesCanon/p/12723510.html
Copyright © 2011-2022 走看看