【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形式的时候,碎片问题会变得更严重。旧空间还未满,又申请新的空间。
【Oracle】表碎片重用规则的更多相关文章
- 08 Oracle表碎片查询以及整理(高水位线)
		
Oracle表碎片查询以及整理(高水位线) 1.表碎片的来源 当针对一个表的删除操作很多时,表会产生大量碎片.删除操作释放的空间不会被插入操作立即重用,甚至永远也不会被重用. 2.怎样确定是否有表碎片 ...
 - Oracle 数据库整理表碎片
		
Oracle 数据库整理表碎片 转载:http://kyle.xlau.org/posts/table-fragmentation.html 表碎片的来源 当针对一个表的删除操作很多时,表会产生大量碎 ...
 - Oracle表空间碎片整理SHRINK与MOVE
		
整理表碎片通常的方法是move表,当然move是不能在线进行的,而且move后相应的索引也会失效,oracle针对上述不足,在10g时加入了shrink,那这个方法能不能在生产中使用呢? ...
 - 【转】Oracle 表空间与数据文件
		
--============================== --Oracle 表空间与数据文件 --============================== /* 一.概念 表空间:是一个或 ...
 - Oracle 表空间与数据文件
		
-============================== --Oracle 表空间与数据文件 --============================== /* 一.概念 表空间:是一个或多 ...
 - oracle表分区以及普表转分区表(转)
		
概述 Oracle的表分区功能通过改善可管理性.性能和可用性,从而为各式应用程序带来了极大的好处.通常,分区可以使某些查询以及维护操作的性能大大提高.此外,分区还可以极大简化常见的管理任务,分区是构建 ...
 - oracle表分区详解
		
原文来自:http://www.cnblogs.com/leiOOlei/archive/2012/06/08/2541306.html oracle表分区详解 从以下几个方面来整理关于分区表的概念及 ...
 - Oracle表空间知识
		
Oracle表空间知识 一,创建临时表空间 CREATE temporary TABLESPACE TEMP_PNLREPORT tempfile '/oradata2/ORCL/temp_pnlre ...
 - 45.oracle表类型、数据拆分、表分区
		
不要做一些没有意义的事情,就比如说你要离职并不打算吃回头草,离职理由中完全没有必要说明“领导的水平太渣,人品太差”此类的原因,而是“个人原因”,当然实在不批准辞职另说. oracle表类型 表的类型分 ...
 
随机推荐
- Java实现 蓝桥杯VIP 算法训练 校门外的树
			
问题描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,--,L,都种 ...
 - Java实现 LeetCode 45 跳跃游戏 II(二)
			
45. 跳跃游戏 II 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位置可以跳跃的最大长度. 你的目标是使用最少的跳跃次数到达数组的最后一个位置. 示例: 输入: [ ...
 - Java实现 LeetCode 9 回文数
			
9. 回文数 判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 示例 1: 输入: 121 输出: true 示例 2: 输入: -121 输出: false ...
 - 源码分析 | 手写mybait-spring核心功能(干货好文一次学会工厂bean、类代理、bean注册的使用)
			
作者:小傅哥 博客:https://bugstack.cn - 汇总系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言介绍 一个知识点的学习过程基本分为:运行helloworld ...
 - C和C++中static的比较
			
using namespace std; class A{ private: static int a;//由static修饰的变量仅仅是一个声明,不能在此处进行初始化,需要在类的外部初始化. voi ...
 - 【shell】十分钟轻松入门;如果没入门,您吐口口水再走吧!
			
一.什么是shell? Shell是什么? 1.Shell 是一个程序,Linux默认是用bash. Shell 是一个用 C 语言编写的程序,既是一种命令语言,又是一种程序设计语言,是用户使用Lin ...
 - 讨论session共享方案设计
			
默认情况下,php的session文件是保存在磁盘文件中. 在php.ini配置文件中的配置项如下: session.save_handler = files session.save_path = ...
 - react中的ref的3种方式
			
2020-03-31 react中的ref的3种方式 react中ref的3种绑定方式 方式1: string类型绑定 类似于vue中的ref绑定方式,可以通过this.refs.绑定的ref的名字获 ...
 - 全网最完整的Redis入门指导
			
前言 本文提供全网最完整的Redis入门指导教程,下面我们从下载Redis安装包开始,一步一步的学习使用. 下载Redis 官网提供的Redis安装包是服务于Linux的,而我们需要在Window下使 ...
 - TensorFlow从0到1之TensorFlow Keras及其用法(25)
			
Keras 是与 TensorFlow 一起使用的更高级别的作为后端的 API.添加层就像添加一行代码一样简单.在模型架构之后,使用一行代码,你可以编译和拟合模型.之后,它可以用于预测.变量声明.占位 ...