Oracle堆表内部存储机制

来源:互联网 发布:杭州淘宝摄影培训班 编辑:程序博客网 时间:2024/05/18 12:44

去年年底某个项目上碰到了一个比较特殊的需求,使用ArcGIS Server出图的是否可以按照要素的面积大小顺序出图,也就是先画面积大的要素,再画面积小的要素。

当时开发商提出的方案是:在应用层面上录入数据的时候按照面积的大小顺序录入,然后读的时候按照当时录入的顺序读出来就可以了,貌似很正确,实际情况并非如此。为啥呢,这就牵扯到Oracle堆表内部的存储机制上了。

下面详细介绍下Oracle存储上内部分配机制是:

Segment —–>Extent——->Block
在Oracle中一个表至少包括一个Segment(如果包括BLOB,CLOB字段的时候,会包括多个段)。

先具体介绍一下区的分配和管理方式,具体见下面测试过程,
创建test表空间和test用户

SQL> create tablespace test datafile 'C:\APP\ORADATA\ORCL\PDBORCL\test.DBF' size 10M autoextend off;表空间已创建。SQL> create user test identified by test default tablespace test;用户已创建。SQL> alter user test quota unlimited on test;用户已更改。SQL> grant connect,resource to test;授权成功。

在test用户下建立一个表test1(不包括BLOB,CLOB字段),并查看段信息

SQL> create table test.test1 (name varchar2(20));表已创建。SQL> select segment_name from dba_segments where owner='TEST';未选定行

发现没有相应的段产生,这是11g的延迟段创建新特性,新建空表只会在数据库的数据字段中添加表信息,不会创建相应的段,只有插入实际数据后才会创建相应的段。

SQL> insert into test.test1 values ('aaaaa');已创建 1 行。SQL> commit;提交完成。SQL> select segment_name from dba_segments where owner='TEST';SEGMENT_NAME----------------------------------------------------------------TEST1

可以看到插入数据后数据库创建了与表名相同的段。

Extent是段的最小分配单位,也就是说段每次分配一个区。

SQL> select extent_id,file_id,block_id,blocks from dba_extents where owner='TEST' and segment_name='TEST1'; EXTENT_ID    FILE_ID   BLOCK_ID     BLOCKS---------- ---------- ---------- ----------         0         11        128          8

可以看出来刚才插入记录的行为导致TEST1段中已经开辟了一个区,该区从128号Block开始包括了8个Block,也就是包括了128–135,这8个Block。

那为啥起始是从128号开始分配的,而不是从0开始,那0—127Block干啥用的。0—127号Block是被系统征用了,其中0,1两个块存储文件头信息,第2个Block是ExtentMap位图头,3—127块是ExtentMap快,是以位图形式来存储文件中Extent的使用状态,将第0,1号Block dump出来,可以看到起存储的问题信息。

SQL> alter system dump datafile 11 block min 0 block max 1;系统已更改。

导出文件中的信息:

*** 2016-02-18 15:11:21.145Start dump data blocks tsn: 5 file#:11 minblk 0 maxblk 1Block 1 (file header) not dumped:use dump file header commandEnd dump data blocks tsn: 5 file#: 11 minblk 2 maxblk 1

导出信息表明0—1是文件头,需要用导出文件头命令导出其信息(具体如何导出在此不进行介绍)。

接着导出第2个Block

SQL> alter system dump datafile 11 block 2;系统已更改。

导出如下信息:

lock dump from cache:Dump of buffer cache at level 4 for pdb=3 tsn=5 rdba=46137346BH (0x7ff70fd6858) file#: 11 rdba: 0x02c00002 (11/2) class: 13 ba: 0x7ff70bdc000  set: 6 pool: 3 bsz: 8192 bsi: 0 sflg: 0 pwc: 0,0  dbwrid: 0 obj: -1 objn: 1 tsn: [3/5] afn: 11 hint: f  hash: [0x7ff946fbd78,0x7ff946fbd78] lru: [0x7ff70fd6a88,0x7ff70fd6808]  ckptq: [NULL] fileq: [NULL]  objq: [0x7ff70fd6ab0,0x7ff82101260] objaq: [0x7ff70fd6ac0,0x7ff82101250]  st: XCURRENT md: NULL fpin: 'ktfbwh00: ktfbhfmt' fscn: 0x0.273209 tch: 2  flags: block_written_once  LRBA: [0x0.0.0] LSCN: [0x0.0] HSCN: [0xffff.ffffffff] HSUB: [3]Block dump from disk:buffer tsn: 5 rdba: 0x02c00002 (11/2)scn: 0x0.273514 seq: 0x02 flg: 0x04 tail: 0x35141d02frmt: 0x02 chkval: 0xd365 type: 0x1d=KTFB Bitmapped File Space HeaderHex dump of block: st=0, typ_found=1Dump of memory from 0x0000000016706000 to 0x0000000016708000016706000 0000A21D 02C00002 00273514 04020000  [.........5'.....]016706010 0000D365 0000000B 00000008 00000500  [e...............]016706020 00000001 00000000 00000000 0000007E  [............~...]016706030 000004FF 00000001 0000008F 00226B3A  [............:k".]016706040 00000000 00000000 00000000 00000000  [................]016706050 00000080 00000008 00000000 00000000  [................]016706060 00000000 00000000 00000000 00000000  [................]        Repeat 504 times016707FF0 00000000 00000000 00000000 35141D02  [...............5]File Space Header Block: Header Control: RelFno: 11, Unit: 8, Size: 1280, Flag: 1 AutoExtend: NO, Increment: 0, MaxSize: 0 Initial Area: 126, Tail: 1279, First: 1, Free: 143 Deallocation scn: 2255674.0 Header Opcode: Save: No Pending Op End dump data blocks tsn: 5 file#: 11 minblk 2 maxblk 2

从Type=KTFB Bitmapped File Space Header信息中可以确定该块的类型为Bitmapped File Space Header。
接着导出第三个块。

SQL> alter system dump datafile 11 block 3;系统已更改。

导出信息如下:

Start dump data blocks tsn: 5 file#:11 minblk 3 maxblk 3Block dump from cache:Dump of buffer cache at level 4 for pdb=3 tsn=5 rdba=46137347BH (0x7ff70f8a6d8) file#: 11 rdba: 0x02c00003 (11/3) class: 12 ba: 0x7ff70440000  set: 5 pool: 3 bsz: 8192 bsi: 0 sflg: 0 pwc: 0,0  dbwrid: 0 obj: -1 objn: 1 tsn: [3/5] afn: 11 hint: f  hash: [0x7ff94dc78f8,0x7ff94dc78f8] lru: [0x7ff70f8a908,0x7ff70f8a688]  ckptq: [NULL] fileq: [NULL]  objq: [0x7ff70f85a70,0x7ff821085b8] objaq: [0x7ff821085a8,0x7ff70f8a6c0]  st: XCURRENT md: NULL fpin: 'ktfbwh01: ktfbbfmt' fscn: 0x0.273209 tch: 2  flags: block_written_once  LRBA: [0x0.0.0] LSCN: [0x0.0] HSCN: [0xffff.ffffffff] HSUB: [2]Block dump from disk:buffer tsn: 5 rdba: 0x02c00003 (11/3)scn: 0x0.273514 seq: 0x01 flg: 0x04 tail: 0x35141e01frmt: 0x02 chkval: 0x4d8e type: 0x1e=KTFB Bitmapped File Space BitmapHex dump of block: st=0, typ_found=1Dump of memory from 0x0000000016706000 to 0x0000000016708000016706000 0000A21E 02C00003 00273514 04010000  [.........5'.....]016706010 00004D8E 0000000B 00000080 00000000  [.M..............]016706020 00000001 0000F7FF 00000000 00000000  [................]016706030 00000000 00000000 00000001 00000000  [................]016706040 00000000 00000000 00000000 00000000  [................]        Repeat 506 times016707FF0 00000000 00000000 00000000 35141E01  [...............5]File Space Bitmap Block: BitMap Control: RelFno: 11, BeginBlock: 128, Flag: 0, First: 1, Free: 63487 0100000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 

从信息中可以看出来该块的类型为KTFB Bitmapped File Space Bitmap,第一个值为
01 00 00 00 00 00 00 00,转换成二进制就是
10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
第一位为1,也就是说第一个Extent已经被分配出去了。

可以手动的为TEST1段多分配几个Extent

SQL> alter table test.test1 allocate extent;表已更改。SQL> alter table test.test1 allocate extent;表已更改。SQL> alter table test.test1 allocate extent;表已更改。SQL>alter table test.test1 allocate extent;表已更改。SQL> select file_id,block_id,blocks from dba_extents where owner='TEST' and segment_name='TEST1';   FILE_ID   BLOCK_ID     BLOCKS---------- ---------- ----------        11        128          8        11        136          8        11        144          8        11        152          8        11        160          8        11        168          8        11        176          8        11        184          8        11        192          8        11        200          8已选择 10 行。

从信息中可以看出,现在128—207这80个Block给TEST1段。
再将Block 3导出来可以看到Extent Map也发生了变化,如下所示:

Start dump data blocks tsn: 5 file#:11 minblk 3 maxblk 3Block dump from cache:Dump of buffer cache at level 4 for pdb=3 tsn=5 rdba=46137347Block dump from disk:buffer tsn: 5 rdba: 0x02c00003 (11/3)scn: 0x0.2754d9 seq: 0x01 flg: 0x04 tail: 0x54d91e01frmt: 0x02 chkval: 0x4e72 type: 0x1e=KTFB Bitmapped File Space BitmapHex dump of block: st=0, typ_found=1Dump of memory from 0x000000001DDD2200 to 0x000000001DDD420001DDD2200 0000A21E 02C00003 002754D9 04010000  [.........T'.....]01DDD2210 00004E72 0000000B 00000080 00000000  [rN..............]01DDD2220 0000000A 0000F7F6 00000000 00000000  [................]01DDD2230 00000000 00000000 000003FF 00000000  [................]01DDD2240 00000000 00000000 00000000 00000000  [................]        Repeat 506 times01DDD41F0 00000000 00000000 00000000 54D91E01  [...............T]File Space Bitmap Block: BitMap Control: RelFno: 11, BeginBlock: 128, Flag: 0, First: 10, Free: 63478 FF03000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 0000000000000000 

从上面导出信息中可以看出ExtentMap已经发生变化,由01 00 00 00 00 00 00变成了
FF 03 00 00 00 00 00, 转换成二进制就是
11111111 11000000 00000000 00000000 00000000 00000000 00000000 00000000
前十位已经被置位了,与SQL语句查出来的结果是一致的。

上面介绍的是区的分配和管理方式,后续会继续介绍段的分配方式,以及全表扫描的机制。

0 0
原创粉丝点击