1、block:是Oracle中存储数据块的最小单位,所以数据最终都是存储在block中。它也被称为逻辑blocks或是页(pages)。每个操作系统都有自己的block size。而这里的block是Oracle自己的,不同于OS的blocks。可以通过设置DB_BLOCK_SIZE设置Oracle的block为OS的block的几倍,从而减少不必要的I/O。不管block中存放的数据是表、索引还是cluster data,block的结构都是一致:
@ block header: 这里主要存储一些数据块的基本信息,如数据块地址,块类型(table data, index等),以及一些事务信息。为了加强理解,我们dump一下block看看:
SQL> select dbms_rowid.rowid_relative_fno(rowid) as fno, dbms_rowid.rowid_block_number(rowid) from t1 where b=1;
FNO DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
———- ————————————
4 388
SQL> alter system dump datafile 4 block 388;
在dump file中,我们看到
Block header dump: 0×01000184
Object id on Block? Y
seg/obj: 0xcd17 csc: 0×00.8d80b itc: 2 flg: E typ: 1 – DATA
brn: 0 bdba: 0×1000181 ver: 0×01 opc: 0
inc: 0 exflg: 0
# 以下是一些比较重要的事务信息,每当一个事务开始时,都要获得一个ITL entry, 否则将会出现ITL 等待。
Itl Xid Uba Flag Lck Scn/Fsc
0×01 0×0002.005.0000010b 0×00800024.0128.32 –U- 66 fsc 0×0000.0008d8f3
0×02 0×0000.000.00000000 0×00000000.0000.00 —- 0 fsc 0×0000.00000000
data_block_dump,data header at 0xceb6864
@ table directory 记录该块中 table rows 的信息,如下所示:
===============
tsiz: 0×1f98
hsiz: 0×96
pbl: 0×0ceb6864
bdba: 0×01000184
76543210
flag=——–
ntab=1 // no. of tables, 除了cluster 以外,一般情况都为一
nrow=66 // 该block 上 rows 的数目
frre=-1
fsbo=0×96
fseo=0×402
avsp=0×36c
tosp=0×36c
@ row directroy 记录该块中记录的每一条记录的地址信息。如下所示:
0×12:pri[0] offs=0×402
0×14:pri[1] offs=0×46d
0×16:pri[2] offs=0×4d8
…
…
0×92:pri[64] offs=0×1ec2
0×94:pri[65] offs=0×1f2d
最终的记录条数应该和table directory 中的nrows相等。这部分空间一旦被分配,将不可能收回,只能在有新行insert时被重用。
** overhead:在block中,上述的header、table directory和row directory被合称为overhead。
@ row data 记录表中的实际数据。
@ free space 该部分主要用于update,insert等操作。 同时ITL entry 也可以在该部分获得。
附注:
## 在data block中的free space的使用与优化:当数据被delete或update时,可能引起block产生free space对此:①如果有insert语句与相应释放block space的语句在同一个transaction中,则insert可以使用刚刚释放的block space;②如果insert语句与相应的释放block space的语句不在同一个transaction中,则释放的block space只有在事务被commit之后才能被使用。Oracle当发生以下两种情况会进行free space的合并:insert或update操作视图使用一个有足够free space的block;free space存在大量碎片,无法进行数据的insert等。
## row的链接与迁移:当一条记录row的数据太大时,可能无法放在一个block中,这种情况下Oracle往往会使用chain(链接)的方法;此外,当one row被update后,数据量增大,当前的block已经不能完全容纳时,Oracle会把该row数据整个迁移(migrates)到其他的数据块中,但在原来row的位置上保存一个指针,链接到新的地址上,大量的迁移、链接将会降低DB的I/O性能。
2、extent:extent 是每次分配给一个对象的逻辑最小单位,是由一定数量连续的block组成。一个或多个extent又组成了一个segment。
@ Extent的分配:对于本地管理表空间,DB会先确定能够分配extent的候选datafile,随后查询该datafile的bitmap,确定是否有所需大小的连续空闲blocks,直到找到满足的datafile。如果使用dictionary managed tablespace,则是去查询数据字典,而不是datafile头部的bitmap信息。另外,由于某些原因,如果想手工非配extent时,可以使用alter table table_name allocate extent。
@ Extent的收回: 当一个extent被分配给了某个object,除非这个obj被drop,否则extent将不会被其他obj所使用。除非 trauncate … drop storage.或者alter table … dealocate unused.(以上两种方法都不适用于index)。另外,对于rollback segments,如果指定了optimal参数,oracle会自己dealocate一些extent。
在dictionary managed tablespace中,如果所请求的ext 大于各个free extents 大小,这是oracle将聚合临近的extent,形成一个更大的extent。在local managed tablespace中,则无此限制。 一旦extent 被分配和回收,相应的文件头bitmap或者数据字典都会被更新。
3、segment:它是extents的集合,它包含了在表空间中所包含的具体逻辑存储机构的所有extents。例如一个未分区的table,index, cluster被成为一个段,一个被分区的index,table的一个partition 被成为一个段。对于temporary segment,主要用于排序等操作,只有当DB的内存无法存放相应的排序操作并无法找到其他更好的解决办法时,才会在临时表空间中创建temporary segment。以下语句都可能要创建temporary segment。CREATE
INDEX
SELECT ... ORDER BY
SELECT DISTINCT ...
SELECT ... GROUP BY
SELECT
. . . UNION
SELECT ... INTERSECT
SELECT ... MINUS