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

数据库版本如下:

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形式的时候,碎片问题会变得更严重。旧空间还未满,又申请新的空间。

最新文章

  1. nodejs 笔记
  2. .NET面试题系列[0] - 写在前面
  3. 100722B
  4. [CentOS7]安装mysql遇到的问题
  5. mysql学习笔记——支持存储引擎
  6. 4630 no pain no game 树状数组
  7. 安装Ubuntu 14.04后要做的5件事情
  8. windows mobile 6.5 隐藏 左下角(左上角)的开始按钮 叉号关闭按钮
  9. Timer和TimerTask
  10. Openjudge-计算概论(A)-比饭量
  11. scoke摘要
  12. hdu 5591 BestCoder Round #65(博弈)
  13. python -- 小数据池 is和 == 再谈编码
  14. VUE实现登录然后跳转到原来的页面
  15. 开源框架.netCore DncZeus学习(四)项目升级
  16. linux中ls -l介绍
  17. Hive-1.2.1_05_案例操作
  18. [Linux] 设置系统时区
  19. LeetCode 476 Number Complement 解题报告
  20. Mysql字段类型与合理选择

热门文章

  1. java中PipedStream管道流通信详细使用(详解)
  2. Linux 用户管理命令-useradd
  3. Node.js躬行记(3)——命令行工具
  4. POJ - 2184 Cow Exhibition 题解
  5. Debian安装NVIDIA显卡驱动
  6. App接口设计之token的php实现
  7. Linux防火墙iptables详解
  8. @loj - 2987@ 「CTSC2016」时空旅行
  9. KVM的web
  10. Windows服务监控工具Perfmon