5.oracle的dump理解五 数据块理论
欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/51228514
前两篇描述了我们在操作层面看到的一些东西,但是没有理论指导,看到越多我们只会越迷糊。所以,蛤蟆从官方文档上摘取一些老少皆宜的内容来补脑。
块是数据块IO的最小单位。
1 数据块和操作系统块
从物理层面,数据库的块存储时候是由操作系统块组成。操作系统块是操作系统可以读写的最小数据单位。ORACLE块是一个逻辑存储结构结构,大小和结构对操作系统是透明的。
如下图1:
数据块大小和操作系统块大小是可以不一样的,数据块请求多个数据块,不是多个操作系统块。
当数据库请求一个数据块,操作系统转换这个请求操作到存储上。数据块的逻辑分离有一下两点:
n 应用层面不需要确定磁盘上数据的物理地址
n 数据块可以条带或镜像到多个物理磁盘
1.1 数据块大小
每个数据块都有一个数据块块大小。有初始化参数DB_BLOCK_SIZE初始化参数在创建库的时候设置。如果没有设置就使用操作系统默认的块大小来制定。标准的数据块大小是4KB或8KB。如果和操作系统块大小不一样,必须是操作系统的倍数。
1.2 表空间块大小
在创建独立的表空间的时候使用不同于DB_BLOCK_SIZE大小的块大小。
2 块格式
每个数据块都有一个格式或内部结构来使能数据块来跟踪数据和空闲空间。存放表,索引还是表族数据都是相似的。
如下图2:
2.1 数据块Overhead
数据块的Overhead蛤蟆不知道翻译成什么,就不翻译了。
数据块使用Overhead来管理块本身。不能用于存储用户数据。这就说明虽然每个块大小假设是8KB,但是实际可用的其实并没有这么多的。
Overhead包含如下几个部分:
2.1.1 块头
块头包含块的通用信息,例如块地址,段类型。对于交易管理的块,块头包含了活动和历史的交易信息。
每个更新块都需要一个交易入口(transaction entry)。ORACLE数据块初始化保留了这些空间。每个交易入口需要的空间取决于操作系统平台。一般是23个字节左右。
2.1.2 表目录
对于堆表,这个目录包含存在这个块的表的元数据块。对于簇表,多个表会存储行在同一个块中。
2.1.3 行目录
对于堆表,该目录描述行在块中的位置。数据块会把行放到块底部的任何位置。行地址记录在该目录向量中。
一个rowid指向特定文件,块和行位置。例如ROWID:AAAPecAAFAAAABSAAA最后3个AAA表示行号.行号是行目录中索引。行目录包含指向块中数据的指针。如果从块中移动一行,数据块会修改行目录中的指针,ROWID保持不变。
数据库在行目录分配空间后,删除行后数据块不会回收这个空间。因此,一个当前是空的块(曾有50行的块)可能分配了100个字节在行目录。数据块在插入行的时候会重新使用这空间。
OverHead中的有些部分是固定的,但是整体是变化的。平均在84~107字节。
2.2 行格式
一个块中除了Overhead,剩下的都是行了。就是真正放数据的地方了。
行数据保持真正的数据,例如表行或索引键。每个数据块有内部格式,每个行也有行格式使得数据块来跟踪数据。
Oracle数据块通过变长记录来存储行。一个行包含一个或多个段。每个段叫做行片(rowpiece),每个行片有一个行头和列数据。
如下图3:
2.2.1 行头
ORACLE数据使用行头来管理行片在块中的存储。行头包含以下信息:
l 行片中的列数量
l 在其他块中的行片(如果完整的行在一个数据块中,那么行作为一个行片,如果不能在一个块中存储,那么会被存储在多个行片中)
l 簇表的簇键
一个块中完整包含一个行至少需要3个字节的行头。
2.2.2 列数据
行头之后,列数据段保存实际的数据。一般,存储列的顺序和CREATE TABLE语句一致,但是顺序不能保证。例如,LONG类型一般最后创建。
在行片中的每个列,数据库分开存储列长度和数据。空间取决于数据类型。如果是可变的,那么会需要空间来增长或变小。
在块头中的行目录上的有个槽指向行。
2.2.3 ROWID格式化
ORACLE使用ROWID来唯一指定一行。ROWID是数据块用来访问行的结构。一个ROWID物理上不存在数据块上,但是和数据所在的文件和块相关。
ROWIW格式如下图4:
分为4个段,第一个是数据对象号,表簇有相同的数据对象号。
第二个是相对文件号,第三个是块号,第四个是行号。
ROWID指向一个行片后,ROWID在一些情况下可以改变。例如,发生行移动,分区键更新,闪回表操作等。
内部数据块执行行移动是物理上先删除然后在插入。但是行移动是被当做UPDATE,可能会触发触发器。
3 块压缩
数据块可以使用表压缩来消除数据块中重复值。
数据块的格式不管是否压缩都是一样的。区别在于,块开始存储时候存储了一个符号表。使用符号表中的短符号来代替重复的值。
例如:
2190,13770,25-NOV-00,S,9999,23,161
2225,15720,28-NOV-00,S,9999,25,1450
34005,120760,29-NOV-00,P,9999,44,2376
9425,4750,29-NOV-00,I,9999,11,979
1675,46750,29-NOV-00,S,9999,19,1121
压缩后如下:
2190,13770,25-NOV-00,S,%,23,161
2225,15720,28-NOV-00,S,%,25,1450
34005,120760,*,P,%,44,2376
9425,4750,*,I,%,11,979
1675,46750,*,S,%,19,1121
使用*来替换29-NOV-00
使用%来替换9999
符号表如下图5:
4 数据块中的空间管理
数据块填充数据块从底部开始,空闲空间位于行数据和块头之间。在UPDATE时候自由空间会减少。数据库管理空闲空间来优化性能避免浪费空间。
4.1 空闲空间百分比
PCTFREE参数指定如何管理自由空间。PCTFREE是重要的避免行迁移和空间浪费。
如果更新少,可以如下设置:
CREATETABLE test_table (n NUMBER) PCTFREE 20;
如下图6所示
PCTFREE设置为20,需要至少有20%的块是空闲的。预留20%是用于现存行更新的使用。
4.2 数据块中优化空闲空间
空间空间的比例不能少于PCTFREE,但是可以超过20%的。
以下命令可以增加块中的空闲空间:
l DELETE
l UPDATE(将存在的值改成更小的值,或者让行发生迁移)
l INSERT(插入唤醒块压缩,导致更多空闲空间)
insert释放空间注意下面2点:
1、 本次交易的插入语句释放后,还是本次交易使用该空间;
2、 如果是其他交易释放的空间,需要其他交易COMMIT后才能使用
4.3 合并碎片空间
释放的空间可能不是连续的,如下图7所示
当一下条件发生时候,ORACLE自动合并空闲空间
l INSERT或UPDATE命令企图使用块中空间来包含新行
l 空闲空间太分散不能插入到块中连续的空间中
合并后,空闲空间就连续了。
合并只有在条件满足才执行,因为会该动作是会影响性能的。
4.4 行连接和行迁移
数据块必须管理太大的行存储在单个块中。
l 当第一次插入时候,行太大。ORACLE存储该行使用段保留的多个块连接。行连接在大行时候经常发生。例如包含LONG或者LONGRAW。不可避免的。
l 当行被更新的长度增加,剩下的空间不能保持更新的行。发生行迁移,将整行移动新的数据块,原来行片中保存一个指针指向新的位置。ROWID并没有发生改变。
l 一行超过255列,一个行片中只能保持255个列。如果超过的话,需要链接多个块了。
当行迁移或链接后,IO就会增加。
5 索引块
索引块是特殊类型的块,和表块有些不同。数据块使用索引块来管理索引的逻辑存储空间。
索引块类型有如下:
根块:索引入口
分支块:搜索索引键时候的导航块
叶块:包含索引键值ROWID,指向表中的相关行。
5.1 索引入口存储
索引入口存储方式和表行在数据块中存储一样。索引在块中的不是按二进制顺序存储,而是用堆的方式。
数据块管理行目录的方式和数据块有些不同。行目录中的是根据键值排序的。提高了索引扫描的效率。
5.2 索引块槽位复用
索引块比堆表的表块有更多行。在一个单独索引块中存储很多行,可以让数据块管理更简单因为可以避免频繁的分裂块。
数据块可以复用索引块中的空间。如果插入一个值到列中,然后删除一个值。当行需要空间的会后,数据块会重新使用之前删掉释放出来的索引槽位。
索引不能合并他们自己,除非手动执行ALTER INDEX REBUILD或者COALESCE选项。
5.3 合并索引块
索引合并压实当前存在索引数据,如果重新组织释放了块,释放的块留在索引结构中,并不释放出来给其他用户。不会自动执行,需要输入ALTER INDEX REBUILD或者COALESCE选项。