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

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

 

bb

 

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_SIZEDB_BLOCK_SIZE应当是操作系统块大小的整数倍数 ,可以有效地避免不必要的I/O,这里的操作系统块指的是簇字节数(I/O chunk size),事实上OracleDB_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日志写入使用512byteschunk大小,因此最好把日志放到裸设备和相关硬件上,从而忽略文件系统。(该观点来自于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引擎向操作系统发出请求,操作系统在通过内核进行相应的系统调用接口读取操作系统块;然后文件系统调用相应的块设备进行扇区数据读写。(裸设备暂时无法理解其原理)

bb

参见《关于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数据,格式都是很类似的,见图

bb


块头(公共和变量)

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

表目录

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

行目录

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

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

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

头部信息区(Overhead

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

可用空间(Free Space

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

行数据

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

 

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

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

 

可用空间管理(Free Space Management)

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

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

使用便捷

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

并发访问的动态调整

性能/空间的平衡

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

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

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

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

释放的空间也可能不是连续的,只有当1一个insertupdate语句试图使用足够空间创建新行的时候,并且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也是用于设置一个百分比,当块中已使用的空间的比例小于这个百分比的时候,这个块才被标识为有效状态。只有有效的块才被允许插入数据

 
创建数据表
create table TEST
(
  NAME VARCHAR2(4000)
)
tablespace XXX
  pctfree 10    --初始化保留的最小10%的空闲空间比例,低于90%是,均可插入
  pctused 40   --当已使用空间比例小于这个百分比时,重新允许插入数据
  initrans 1
  maxtrans 255
  storage
  (
    initial 64K
    minextents 1
    maxextents unlimited
  );
--插入测试数据,并观察其相应的rowid
insert into test values('1');
insert into test values('2');
insert into test values('3');
commit;
select t.*,t.rowid from test t;
update test set name=lpad(name,4000,'1') where name='1';
update test set name=lpad(name,4000,'2') where name='2';
update test set name=lpad(name,4000,'3') where name='3';
commit;
select t.*,t.rowid from test t;

--创建数据字典表chained_rows
@F:\OracleForVista\product\10.2.0\db_1\RDBMS\ADMIN\utlchain.sql;
--分析相关表
ANALYZE TABLE test LIST CHAINED ROWS;
--查询链接行或迁移行
SELECT * FROM CHAINED_ROWS where table_name='TEST';
select t.*,t.rowid from test t;
行迁移解决办法:其实没有太好的办法,只能是行迁移数据删除后,重新插入回来
Create table new_table as select * from old_table;
Drop table old_table;
Rename new_table to old_table;
Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONEfj.pngimage002.jpg

fj.pngimage005.jpg

fj.pngimage007.jpg

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/6517/viewspace-545695/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/6517/viewspace-545695/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值