Oracle的逻辑结构(表空间、段、区间、块)——Oracle数据块(一)

原创于2009年02月10日,2009年10月22日迁移至此。


Oracle 的逻辑结构 ( 表空间、段、区间、块 ) ——块

 

Oracle的逻辑结构(表空间、段、区间、块)——Oracle数据块(一)_第1张图片

 

Oracle 存储数据的最小单位是数据块。Oracle 管理 数据库 数据文件的存储空间被称为数据块,一个数据块是数据库使用的最小数据单位。对应的操作系统层面上,所有数据都是以字节形式存储的。每一种操作系统都有自己的块大小。Oracle 对数据的请求是Oracle 数据块的倍数,而非操作系统块。

标准的块大小是通过初始化参数DB_BLOCK_SIZE 指定的,Oracle 允许指定最多5 种非标准块。为了避免不必要的I/O 开销,数据块大小应当是操作系统块大小的整数倍。

关于数据块的几个概念

磁盘扇区 大小 512bytes sector size ,操作系统空间分配块大小, OS space allocation block size

簇字节数 也就是 I/O chunk size ,通常所说的操作系统块大小

Oracle 数据块 DB_BLOCK_SIZE DB_BLOCK_SIZE 应当是操作系统块大小的整数倍数 ,可以有效地避免不必要的 I/O ,这里的操作系统块指的是簇字节数 (I/O chunk size) ,事实上 Oracle DB_BLOCK_SIZE 大小可以小于簇字节数 (I/O chunk size) ,所以 Oracle 官方文档写的是应当或者建议值。

The standard block size is specified by the initialization parameter DB_BLOCK_SIZE . In addition, you can specify of up to five nonstandard block sizes. The data block sizes should be a multiple of the operating system’s block size within the maximum limit to avoid unnecessary I/O. Oracle data blocks are the smallest units of storage that Oracle can use or allocate. (来自于 Oracle Concept

 

Oracle 日志写入使用 512bytes chunk 大小,因此最好把日志放到裸设备和相关硬件上,从而忽略文件系统。 ( 该观点来自于 itpub Yong Huang ,但是原文出处不可考证 ) Oracle 日志和数据文件写入机制的不同,印证了 redo 文件最好与其它数据文件进行物理分离。

Since Oracle redo writing uses chunk size of 512 bytes (or 1k on HPUX and a few other OS'es), it's always better to place redo logfiles on raw partitions or equivalent (Veritas Quick I/O, Oracle ASM etc), bypassing filesystems.

 

正常情况下,可以认为服务器进程读取相应的 Oracle 块时,会调用 Oracle I/O 引擎,然后 Oracle I/O 引擎向操作系统发出请求,操作系统在通过内核进行相应的系统调用接口读取操作系统块;然后文件系统调用相应的块设备进行扇区数据读写。 ( 裸设备暂时无法理解其原理 )

Oracle的逻辑结构(表空间、段、区间、块)——Oracle数据块(一)_第2张图片
ITPUB个人空间3m J+f1U's�Y#i[ {@

参见《 关于 oracle 数据块和操作系统块的关系》

http://www.itpub.net/viewthread.php?tid=1081114&highlight=%CA%FD%BE%DD%BF%E9

chkdsk 可以查看操作系统的块大小 (windows 平台 )

fsutil fsinfo ntfsinfo c: 命令也可查看操作系统的块大小 (windows 平台 )

/sbin/tune2fs -l /dev/sda1 | grep Block 可以查看操作系统的块大小 (Linux 平台 )

show parameter db_block_size 显示 Oracle 缺省数据块大小

区间是一系列用来存储特定信息的连续的数据块

 

数据块格式

Oracle 数据块的格式无论是表、索引还是cluster 数据,格式都是很类似的,见图

Oracle的逻辑结构(表空间、段、区间、块)——Oracle数据块(一)_第3张图片
ITPUB个人空间 q`,J jI'U~7[

ITPUB个人空间o8n"M(o8K0_:}

块头( 公共和变量)

头部包含了通用块信息,例如块的地址和段的类型 ( 例如表或者索引 )

表目录

这部分信息包含了在这个块中该表或该索引的相关信息。

行目录

这部分包含了数据块中的实际行的信息 ( 包括行数据区域中每行的地址 ) ,一旦数据块头部的这个行目录的空间被分配了,那么即使该行删除了,这段空间仍然不能回收。

因此一个当前为空的数据块

此区域包含数据块中存储的数据行的信息(每个数据行片断( row piece 在行数据区( row data area )中的地址)。 [ 一个数据块中可能保存一个完整的数据行,也可能只保存数据行的一部分 ,所以文中使用 row piece] 。只有在数据块中插入( insert )新数据时,行目录区空间才会被重新利用。

头部信息区(Overhead

块头( header/Common and Variable ),表目录( Table Directory ),行目录( Row Directory )这三部分合称为头部信息区( Overhead )。头部信息区不存放数据,它存放的整个块的信息。头部信息区的大小是可变的。一般来说,头部信息区的大小介于 84 字节( bytes )到 107 字节( bytes )之间

可用空间(Free Space

可用空间是一个块中未使用的区域,这片区域用于新行的插入和已经存在的行的更新。可用空间也包含事务条目,当每一次 insert update delete select ..for update 语句访问块中一行或多行数据,将会请求一条事务条目,事务条目的请求空间与操作系统相关,在多数操作系统中大约所需 23 个字节。

行数据

这部数据块包含了表或索引的数据,行也可能跨数据块,这也就是行迁移现象。

 

具体参见: oracle 数据文件内部 BLOCK 结构详解,初始原文已不可考

http://www.sosdb.com/article/datafile_block.htm

 

可用空间管理(Free Space Management)

可用空间可能是自动或人工管理。

可用空间是由 Oracle 内部的段自动管理的,段内的可用 / 已用空间用位图来跟踪。自动段空间管理提供了以下好处:

l  使用便捷

l  更好的空间利用率,特别是那些行大小变化很大的对象

l  并发访问的动态调整

l  性能 / 空间的平衡

数据块可用空间的利用和压缩

Delete update( 把原值变小 ) 可增加数据块的可用空间。在以下情况下 insert 语句才能有效地利用已释放的空间。

假如 insert 语句在同一个事务中,而 insert 前面的语句刚好释放了相应的空间,这时候 insert 语句可以利用该空间

假如 insert 语句与释放空间的语句不在同一个事务中,那么只有当其他事务提交后并且刚好需要空间的时候, insert 语句才能利用该空间。

释放的空间也可能不是连续的,只有当 1 一个 insert update 语句试图使用足够空间创建新行的时候,并且 2 自由空间是分散的以至于不能插入毗邻空间的时候, Oracl 才会合并和压缩数据块的可用空间。

 

行链接和行迁移(Row Chaining and Migrating

行链接( Row Chaining ):如果我们往数据库中插入( INSERT )一行数据,这行数据很大,以至于一个数据块存不下一整行, Oracle 就会把一行数据分作几段存在几个数据块中,这个过程叫行链接( Row Chaining )。

如果一行数据是普通行,这行数据能够存放在一个数据块中;如果一行数据是链接行,这行数据存放在多个数据块中。

行迁移 (Row Migrating) :数据块中存在一条记录,用户执行 UPDATE 更新这条记录,这个 UPDATE 操作使这条记录变长,这时候, Oracle 在这个数据块中进行查找,但是找不到能够容纳下这条记录的空间,无奈之下, Oracle 只能把整行数据移到一个新的数据块。原来的数据块中保留一个“指针”,这个“ 指针”指向新的数据块。被移动的这条记录的 ROWID 保持不变。

 

PCTFREE 参数用于指定块中必须保留的最小空闲空间百分例。之所以要预留这样的空间,是因为 UPDATE 时,需要这些空间。如果 UPDATE 时,没有空余空间, Oracle 就会分配一个新的块,这会产生行迁移( Row Migrating )。

PCTUSED 也是用于设置一个百分比,当块中已使用的空间的比例小于这个百分比的时候,这个块才被标识为有效状态。只有有效的块才被允许插入数据

 
v*C3mBa!fg1si6517 创建数据表
c"f /^:Na?6517 create table TEST
i!m"zw�E:^|6517 (
.?9^R HV5{dmAR6517   NAME VARCHAR2(4000)
,RX8f4O r2r6517 )ITPUB个人空间xS)D!O-?c1a~
tablespace XXXITPUB个人空间%h I v vOC
  pctfree 10    --初始化保留的最小10%的空闲空间比例,低于90%是,均可插入ITPUB个人空间%b9tH/{ d%{:a:G
  pctused 40   --当已使用空间比例小于这个百分比时,重新允许插入数据ITPUB个人空间3v-]!|wD I*UB
  initrans 1
a.X$~~wdN6517   maxtrans 255
Gyvp-q*h+uo0J-p"I6517   storage
5r-L YW1~4m Mc:o6517   (
K_(r/JVht pa6517     initial 64K
$H:{!r]_1k/u6517     minextents 1
z{,VTS6517     maxextents unlimitedITPUB个人空间3i6[y8dr
  );
!IcR.WZD1d6517 --插入测试 数据,并观察其相应的rowid
Ee4fd }(w+k6517 insert into test values('1');ITPUB个人空间0D*@E&dgpi-x"v
insert into test values('2');
/ N"jI-M]6517 insert into test values('3');
.L4D$E7o)E4]s2{6517 commit;
aZHX5Pp6517 select t.*,t.rowid from test t;
/?AK%@1rs]%z3s6517 update test set name=lpad(name,4000,'1') where name='1';
^4q? P5u_�ki6517 update test set name=lpad(name,4000,'2') where name='2';ITPUB个人空间v/d e8X$FE
update test set name=lpad(name,4000,'3') where name='3';ITPUB个人空间lW/e3HEY
commit;
Ui7G:D*` mnI#j'p6517 select t.*,t.rowid from test t;ITPUB个人空间/n8j VMb0o7O)z4Q0/

E}4RY[UGj/f6517 --创建数据字典表chained_rows
^NI*F7AJJ8zIN6517 @F:/OracleForVista/product/10.2.0/db_1/RDBMS/ADMIN/utlchain.sql;
J0k9^"Oyb3RkE6517 --分析相关表
/`H6rA�K(P6517 ANALYZE TABLE test LIST CHAINED ROWS;
^#|w@ k+p&gl+UG6517 --查询链接行或迁移行
4~7^@0k[LQ9vi6517 SELECT * FROM CHAINED_ROWS where table_name='TEST';
tQeF?6517 select t.*,t.rowid from test t;ITPUB个人空间'u"^WUK+~ ha/
行迁移解决办法:其实没有太好的办法,只能是行迁移数据删除后,重新插入回来ITPUB个人空间N.KY%me+Pi
Create table new_table as select * from old_table;ITPUB个人空间+? c6g"hX*^oy
Drop table old_table;
L owM-z&]i&y9xJ6517 Rename new_table to old_table;

你可能感兴趣的:(Oracle的逻辑结构(表空间、段、区间、块)——Oracle数据块(一))