ITPub博客

首页 > Linux操作系统 > Linux操作系统 > Data block Structure and Row Piece Structure_20091209

Data block Structure and Row Piece Structure_20091209

原创 Linux操作系统 作者:gdutllf2006 时间:2009-12-10 22:25:57 0 删除 编辑

Data block Structure and Row Piece Structure

目标:搞清Data Block 与 Row Piece的物理结构,理解Oracle 如何存储行数据

参考文档

P118<>

P260<>

 

目录

1 Data Block Format

2 Data Block Free Space Management

3 释放的空间可以被重用的条件

4 Oracle coalesces the free space of a data block only when(Coalesces空间的条件)

5 Row Chaining and Migrating

6 PCTFREE, PCTUSED, and Row Chaining

7 How table data is stored

8 Row Piece Format

9 Rowids of Row Pieces

10 Column Order

11 测试

11.1 正常情况下, 只占了一个row piece

11.2 当columns 个数大于等于256时,出现的分成两个row pieces的情形.

11.3 测试column 小于 256时单行数据跨块的情形

12 Notes

 

1 Data Block Format

The Oracle data block format is similar regardless of whether the data block contains table, index, or clustered data.

Block Header: The header contains general block information. Such as the block address and the type of segment (for example, data or index).

 

Table Directory: contains information about the table who have rows in this block.

 

Row Directory: contains information about the actual rows in the block (including address of each row piece in the data area). Once the space was allocated in the row directory, this space is not reclaim(回收)even the row is deleted. Oracle reuses(重用) the space only when new rows are inserted in the block.

 

Overhead: The data block header, table directory and row directory are referred to collectively as overhead. Some block overhead is fixed size; the total block overhead size is variable. On average, the fixed and variable portions of data block overhead total 84 to 107 bytes.

 

Row data: This portion of the data block contains table or index data. Rows can span blocks

 

Free space: Free space is allocated for insertion of new rows and for updates to rows that require additional space. Whether issued insertions actually occur in a given data block is a function of current free space in that data block and the value of the space management parameter PCTFREE.

In data blocks allocated for the data segment of a table or cluster, or for the index segment of an index, free space can also hold transaction entries. A transaction entry is required in a block for each INSERT, UPDATE, DELETE, and SELECT...FOR UPDATE statement accessing one or more rows in the block. The space required for transaction entries is operating system dependent; however, transaction entries in most operating systems require approximately 23 bytes. (Transaction entries 的固定开销大约23 bytes in Free Space portion)

 

2 Data Block Free Space Management

Free space can be managed automatically or manually

Auto: The in-segment free/used space is tracked using bitmaps

Manual: The in-segment free/used space is tracked using free lists.

 

Two types statement can increase the free space of one or more data blocks: DELETE statements, and UPDATE statements that update existing values to smaller values. (两种释放datablock空间的语句:Delete and update to smaller value. 但释放的空间并不能被立即被重用)

 

3 释放的空间可以被重用的条件

1) If the INSERT statement is in the same transaction and subsequent to the statement that frees space, then the INSERT statement can use the space made available. (在同个事务,且insert紧跟delete操作)

 

2) If the INSERT statement is in a separate transaction from the statement that frees space (perhaps being run by another user), then the INSERT statement can use the space made available only after the other transaction commits and only if the space is needed. (不在同个事务,只有在释放空间的事务提交后,且释放的空间正是申请空间的事务所需的大小)

 

4 Oracle coalesces the free space of a data block only when(Coalesces空间的条件)

(1) An INSERT or UPDATE statement attempts to use a block that contains enough free space to contain a new row piece.

(2) The free space is fragmented so the row piece cannot be inserted in a contiguous section of the block.

Oracle does this compression only in such situations, because otherwise the performance of a database system decreases due to the continuous compression of the free space in data blocks.

 

5 Row Chaining and Migrating

In two circumstances, the data for a row in a table may be too large to fit into a single data block. In the first case, the row is too large to fit into one data block then it is first inserted. In this case, Oracle stores the data for the row in a chain of data blocks (one or more) reserved for that segment. Row chaining most often occurs with large rows, such as rows that contain a column of datatype LONG or LONG RAW. Row chaining in these cases is unavoidable.

However, in the second case, a row that originally fit into one data block is updated so that the overall row length increases, and the block’s free space is already completely filled. In this case, Oracle migrates the data for the entire row to a new data block, assuming the entire row can fit in a new block. Oracle preserves the original row piece of a migrated row to point to the new block containing the migrated row. The rowid of a migrated row does not change. When a row is chained or migrated, I/O performance associated with this row decreases because Oracle must scan more than one data block to retrieve the information for the row.

 

6 PCTFREE, PCTUSED, and Row Chaining

For manually managed tablespaces, two space management parameters, PCTFREE and PCTUSED, enable you to control the use of free space for inserts and updates to the rows in all the data blocks of a particular segment. Specify these parameters when you create or alter a table or cluster (which has its own data segment). You can also specify the storage parameter

 

7 How table data is stored

When you create a table, Oracle automatically allocates a data segment in a tablespace to hold the table’s future data. You can control the allocation and use of space for a table’s data segment in the following two ways:

Setting the storage parameters for the data segment.设置segment 参数

Setting the storage parameters for the data block.   设置block参数

(具体的参数细节要参考相应的文档?未整理)

 

Oracle stores each row of a database table containing data for less than 256 columns as one or more row pieces. If an entire row can be inserted into a single data block, then Oracle stores the row as one row piece. However, if all of a row’s data cannot be inserted into a single data block or an update to an existing row causes the row to outgrow its data block, Oracle stores the row using multiple row pieces. A data block usually contains only one row piece for each row. When Oracle must store a row in more than one row piece, it is chained across multiple blocks.

When a table has more than 255 columns, rows that have data after the 255 column are likely to be chained within the same block. This is called intra-block chaining. A chained row’s pieces are chained together using the rowids of the pieces. (如果一个表小于256列,Oracle将表中的单行数据存储在单个数据块中作为一个Row Piece,如果由于初始太大或者由于更新导致太大,导致不能在单个数据中存放时,Oracle会将多余的数据存放在另一个Block中,这样就生多个Row Pieces,从而形成Chain,但仍有一个Rowid. A data block usually contains only one row piece for each table row data. Chain spans multiple blocks. 如果一个表大于256列,则第255列之后的数据可能被chained within the same block.这就是 intra-block chaining,而不会span multiple blocks。)

 

8 Row Piece Format

 

The row header precedes the data and contains information about:

1)     Row pieces

2)     Chaining(for chained row pieces only)

3)     Columns in the row piece

4)     Cluster keys(for clustered data only)

A row fully contained in one block has at least 3 bytes of row header. After the row header information, each row contains column length and data. The column length requires 1 byte for columns that store 250 bytes or less, or 3 bytes for columns that store more than 250 bytes, and precedes the column data. Space required for column data depends on the datatype. If the datatype of a column is variable length, then the space required to hold a value can grow and shrink with updates to the data.

To conserve space, a null in a column only stores the column length (zero). Oracle does not store data for the null column. Also, for trailing null columns, Oracle does not even store the column length. (Each row also uses 2 bytes in the data block header’s row directory,见第一个图)

Clustered rows contain the same information as nonclustered rows. In addition, they contain information that references the cluster key to which they belong. (Cluster rows包含cluster key信息)

 

9 Rowids of Row Pieces

The rowed identifies each piece by its location or address. After they are assigned, a given row piece retains its rowed until the corresponding row is deleted or exported and imported using the Export and Import Utilities. Because rowids are constant for the lifetime of a row piece, it is useful to refer rowid in SQL statements such as SELECT, UPDATE, and DELETE.(rowid 是一个常量)

 

10 Column Order

The column order is the same as they were listed in the CREATE TABLE statement, but this is not guaranteed. Long type column is always stored in the last. To conserve space, a null in a column only stores the column length (zero). Oracle does not store data for the null column. Also, for trailing null columns, Oracle does not even store the column length. So try to place columns that frequently contain nulls last. (Column Order 顺序没保证)

 

 

11 测试

 

11.1 正常情况下, 只占了一个row piece

 

 

SQL> desc t2;

 Name                                      Null?    Type

 ----------------------------------------- -------- ----------------------------

 ID                                                 NUMBER

 NAME                                               VARCHAR2(20)

 

select dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid) from t2;

 

alter system dump datafile 4 block  14362;

 

 

Start dump data blocks tsn: 3 file#: 4 minblk 14362 maxblk 14362

buffer tsn: 3 rdba: 0x0100381a (4/14362)

scn: 0x0000.00070ba3 seq: 0x01 flg: 0x06 tail: 0x0ba30601

frmt: 0x02 chkval: 0xef35 type: 0x06=trans data

Block header dump:  0x0100381a

 Object id on Block? Y

 seg/obj: 0x1796  csc: 0x00.70a55  itc: 2  flg: O  typ: 1 - DATA

     fsl: 0  fnx: 0x0 ver: 0x01

 

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0005.00b.00000029  0x0080004c.0227.2c  C---    0  scn 0x0000.00070a2f

0x02   0x0006.01b.0000002f  0x0080005f.0017.24  --U-    1  fsc 0x0000.00070ba3

 

data_block_dump,data header at 0x3fb985c

===============

tsiz: 0x1fa0

hsiz: 0x14

pbl: 0x03fb985c

bdba: 0x0100381a

     76543210

flag=--------

ntab=1

nrow=1

frre=-1

fsbo=0x14

fseo=0x1f89

avsp=0x1f80

tosp=0x1f80

0xe:pti[0]      nrow=1  offs=0

0x12:pri[0]     offs=0x1f89

block_row_dump:

tab 0, row 0, @0x1f89

tl: 12 fb: --H-FL-- lb: 0x2  cc: 2

col  0: [ 2]  c1 02

col  1: [ 5]  6d 6f 75 73 65

end_of_block_dump

End dump data blocks tsn: 3 file#: 4 minblk 14362 maxblk 14362

 

11.2 当columns 个数大于等于256时,出现的分成两个row pieces的情形.即intra-block chaining

Create table t_column(a number);

 

declare

v_string varchar(100);

begin

for i in 2 .. 260 loop

v_string := 'alter table t_column add col_' || i || ' number';

execute immediate v_string;

end loop;

end ;

/

 

insert into t_column values(

1  ,

2  ,

3  ,

4  ,

5  ,

6  ,

7  ,

8  ,

9  ,

10 ,

...省略

250,

251,

252,

253,

254,

255,

256,

257,

258,

259,

260

);

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> select SEGMENT_NAME, BLOCK_ID start_block_id, BLOCK_ID+BLOCKS-1 end_block_id from dba_extents where segment_name='T_COLUMN';

 

SEGMENT_NAME                                                                     START_BLOCK_ID END_BLOCK_ID

-------------------------------------------------------------------------------- -------------- ------------

T_COLUMN                                                                                  14369        14376

 

 

SQL> select SEGMENT_NAME, BLOCK_ID start_block_id, BLOCK_ID+BLOCKS-1 end_block_id

  2  from dba_extents

  3  where BLOCK_ID between 14369 and 14376;

 

SEGMENT_NAME                                                                     START_BLOCK_ID END_BLOCK_ID

-------------------------------------------------------------------------------- -------------- ------------

T_COLUMN                                                                                  14369        14376

 

可知在 block id in (14369-14376)上只有一个 Segment

 

SQL> select dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid) from t_column;

 

DBMS_ROWID.ROWID_RELATIVE_FNO( DBMS_ROWID.ROWID_BLOCK_NUMBER(

------------------------------ ------------------------------

                             4                          14370

 

Dump block

 

SQL> alter system dump datafile 4 block 14370;

 

System altered.

 

查看DUMP文件

 

*** 2009-12-10 11:07:46.097

*** SESSION ID:(11.7) 2009-12-10 11:07:46.096

Start dump data blocks tsn: 3 file#: 4 minblk 14370 maxblk 14370

buffer tsn: 3 rdba: 0x01003822 (4/14370)

scn: 0x0000.0007e745 seq: 0x01 flg: 0x02 tail: 0xe7450601

frmt: 0x02 chkval: 0x0000 type: 0x06=trans data

Block header dump:  0x01003822

 Object id on Block? Y

 seg/obj: 0x17a2  csc: 0x00.7e743  itc: 3  flg: O  typ: 1 - DATA

     fsl: 0  fnx: 0x0 ver: 0x01

 

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0007.00c.00000039  0x00800169.001e.2b  --U-    2  fsc 0x0000.0007e745

0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000

0x03   0x0000.000.00000000  0x00000000.0000.00  C---    0  scn 0x0000.00000000

 

data_block_dump,data header at 0x3fb9874

===============

tsiz: 0x1f88

hsiz: 0x16

pbl: 0x03fb9874

bdba: 0x01003822

     76543210

flag=--------

ntab=1

nrow=2

frre=-1

fsbo=0x16

fseo=0x1bd1

avsp=0x1bbb

tosp=0x1bbb

0xe:pti[0]    nrow=2   offs=0

0x12:pri[0]   offs=0x1be9

0x14:pri[1]   offs=0x1bd1

block_row_dump:

tab 0, row 0, @0x1be9

tl: 927 fb: -----L-- lb: 0x1  cc: 255

col  0: [ 2]  c1 07

col  1: [ 2]  c1 08

col  2: [ 2]  c1 09

col  3: [ 2]  c1 0a

col  4: [ 2]  c1 0b

col  5: [ 2]  c1 0c

col  6: [ 2]  c1 0d

col  7: [ 2]  c1 0e

col  8: [ 2]  c1 0f

col  9: [ 2]  c1 10

col 10: [ 2]  c1 11

.....省略

col 250: [ 3]  c2 03 39

col 251: [ 3]  c2 03 3a

col 252: [ 3]  c2 03 3b

col 253: [ 3]  c2 03 3c

col 254: [ 3]  c2 03 3d

tab 0, row 1, @0x1bd1

tl: 24 fb: --H-F--- lb: 0x1  cc: 5

nrid:  0x01003822.0

col  0: [ 2]  c1 02

col  1: [ 2]  c1 03

col  2: [ 2]  c1 04

col  3: [ 2]  c1 05

col  4: [ 2]  c1 06

end_of_block_dump

End dump data blocks tsn: 3 file#: 4 minblk 14370 maxblk 14370

 

 

从上面的DUMP文件可以看出,一个row分成了两个row piece

 

tab 0, row 1, @0x1bc9

tl: 24 fb: --H-F--- lb: 0x1  cc: 5

nrid:  0x04000196.0

 

看上面的fb,标示为H和F,H代表Head piece of row ,F代表First data piece

nrid:  0x04000196.0        下一个row piece的地址

 

tab 0, row 0, @0x1be1

tl: 927 fb: -----L-- lb: 0x1  cc: 255

看上面的fb,标示为L,L代表Last data piece

 

11.3 测试column Number小于 256列时单行数据跨块的情形

 

如何测试?参考<中行迁移和行链接的清除及检测_20091210.doc>>

 

如何查看行数据有没有跨块, 在dump文件中查找nrid标记

idle>  create table t2(col1 char(2000),col2 char(2000),col3 char(2000),col4 char(2000),col5 char(2000));

 

Table created.

idle> insert into t2 values('1','2','3','4','5');

 

1 row created.

 

idle> commit;

 

Commit complete.

 

idle>  select dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid) from t2;

 

DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)

------------------------------------ ------------------------------------

                                   6                                   15

 

idle> alter system dump datafile 6 block 15;

 

System altered.

 

查看dump 文件 nrid:  0x0180000e.0 表明有行迁移

 

*** 2004-07-21 00:40:22.970

Start dump data blocks tsn: 6 file#: 6 minblk 15 maxblk 15

buffer tsn: 6 rdba: 0x0180000f (6/15)

scn: 0x0000.000f6ad7 seq: 0x01 flg: 0x02 tail: 0x6ad70601

frmt: 0x02 chkval: 0x0000 type: 0x06=trans data

Block header dump:  0x0180000f

 Object id on Block? Y

 seg/obj: 0x7184  csc: 0x00.f6ad6  itc: 2  flg: E  typ: 1 - DATA

     brn: 0  bdba: 0x1800009 ver: 0x01

     inc: 0  exflg: 0

 

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0008.018.0000009e  0x008000bf.0033.09  --U-    1  fsc 0x0000.000f6ad7

0x02   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000

 

data_block_dump,data header at 0xad7d464

===============

tsiz: 0x1f98

hsiz: 0x14

pbl: 0x0ad7d464

bdba: 0x0180000f

     76543210

flag=--------

ntab=1

nrow=1

frre=-1

fsbo=0x14

fseo=0x179f

avsp=0x178b

tosp=0x178b

0xe:pti[0]    nrow=1   offs=0

0x12:pri[0]   offs=0x179f

block_row_dump:

tab 0, row 0, @0x179f

tl: 2041 fb: --H-F--N lb: 0x1  cc: 2

nrid:  0x0180000e.0

col  0: [2000]

 31 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20

 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20

 ……… 省略…

 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20

col  1: [28]

 32 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20

 20 20 20

end_of_block_dump

End dump data blocks tsn: 6 file#: 6 minblk 15 maxblk 15

 

12 Notes

1) Table can be define up to 1000 columns the same as views

 

2) 假定一个8K的data block,有多少个row piece呢,一个row piece多大,开销多大 ?row piece并没有固定的大小,只是指存储的一行数据。参考Data block的结构,有哪些视图可用来查询,什么时候才跨块,是不能在single datablock 存放下时,做测试

 

3)Default Values for Columns: If a default values is not explicitly defined for a column, then the default for the column is implicitly set to NULL.

 

4) 一个block中可以存放多个table的数据 ?

不能吧

Block=>extent=>Segment=table

 

5) 关于Block的详细解析以后再研究

参考<物理结构详解_20091210.doc>>

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

请登录后发表评论 登录
全部评论

注册时间:2009-07-08

  • 博文量
    133
  • 访问量
    425870