Oracle的段空间分配

简介:

一、基本概念

一个表空间由若干个数据文件组成,表空间的属性可以从dba_tablespaces中获取:

SQL> desc dba_tablespaces;

TABLESPACE_NAME    名称

 BLOCK_SIZE        一个blocik的大小,

 INITIAL_EXTENT    分配给一个segment的第一个extent的大小,以字节为单位 NEXT_EXTENT,第二个extent的大小等于next的值,以后的next=前一next*(1+pctincrease/100)

 MIN_EXTENTS       segment 第一次创建时分配的extent数量

 MAX_EXTENTS       一个segment最多的extent数量                                              

 PCT_INCREASE      见next_extent                                            

 MIN_EXTLEN                             

 STATUS            状态 online|offline                                           

 CONTENTS          permanent|temp|undo                                           

 LOGGING           是否记录redo                                            

 FORCE_LOGGING     yes|no对表空间里的segment记录redo,即使该segment的logging属性logging       

 EXTENT_MANAGEMENT local | dictionary                                               

 ALLOCATION_TYPE   system|uniform extent的分配类型:系统分配,或者是统一

  PLUGGED_IN                                                    

 SEGMENT_SPACE_MANAGEMENT   段管理 manual|auto 手动后自动                                   

 DEF_TAB_COMPRESSION                                           

 RETENTION                                                     

 BIGFILE                           是否大文件(10g)                            

 

  • 本地管理或字典管理,两种方式的差别是表空间中extends的使用信息存放在表空间本身还是存在在数据字典中。本地管理比字典管理的性能要好,因为减少了访问数据字典的冲突。
  • 段空间管理,自动管理使用位图管理段的可用空间,手动使用链表管理,需要设置pctused,freelists,freelists groups 等参数。通常自动比手动性能要好。
  • Extent的分配,可以是autoallocate (自动分配)或 uniform(统一大小)。自动分配模式下,extent的大小由系统决定,通常初始是8个block,之后逐渐增加,这样segment的空闲空间比较多。Uniform模式下,每个extent的大小是一致的,空闲的空间比较少。对于数据量增长比较稳定,而且知道增长量的大小,可设置合适的uniform大小。
  • 用户表空间, extent建议使用本地管理,segment 建议使用自动管理
  • 创建表空间的时候,如果指定extent management local,就不能再指定default storage子句。default storage子句包含了INITIAL_EXTENT、NEXT_EXTENT、MIN_EXTENTS、MIN_EXTENTS、MAX_EXTENTS、PCT_INCREASE这些参数。
  • 9.2版本以上,若system表空间是local manage,则不能创建dictionary manage的表空间。
  • 区管理和段管理方式在创建表空间时指定,之后不能再改,只有本地管理表空间可以使用自动的段空间管理方式。

二、数据文件的组织和段的空间分配

用得最多的是extent本地管理,segment自动管理的表空间。这种情况下,每个段使用位图来记录空间的使用情况,位图分为三个级别,L0,L1,L2 .其中第一个L0块就是段头,L0-L1-L2是一种树形结构。

BMB : bitmap block

 

以下是一个数据文件可能的例子:

 

Lmt使用(数据文件的前8个 block)

Segment 1 extent 0

First level bmb (L1)

second lev el bmb (L2)

Segment header(L0)

Data block

Data block

Data block

Data block

Data block

Segment 1 extent 1

Data block

Data block

Data block

Data block

Data block

Data block

Data block

Data block

Segment 1 extent 2

L2

Data block

Data block

Data block

Data block

Data block

Data block

Data block

Segment 2 extent 0

L1

L2

Segment header(L0)

Data block

Data block

Data block

Data block

Data block

Segment 2 extent 1

Data block

Data block

Data block

Data block

Data block

Data block

Data block

Data block

……

……

……

……

……

……

……

……

……

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

每格为1个block,block size为8k,每个extent有8个block

每个数据文件最前面的8个块,是LMT用于管理extent分配的,每一个segmen的前三个block分别是bmb L1,bmb L2,和段头信息(L0),L1还会出现在其它extent中,但不是每个extent都会有L1。

 

三、通过直接路径插入和间接路径插入的对比来了解段的空间分配(在ITPUB晶晶小妹文章中的例子基础上)

直接路径插入与间接路径插入

  • 采用直接路径插入方式向一个表插入记录时,不需要将该表原有的记录读入缓存,而直接在其物理数据块的高水位(hwm)后插入记录,因此提高了数据插入的效率,且不产生redo数据,而是通过高水位的值来进行回滚操作。使用直接路径插入的语句有create table as select 和inert 。
  • 采用间接路径插入方式向一个表插入记录时,先将该表原有记录的数据块读入缓存,然后在缓存中插入新记录,数据块成为脏数据,再等待dbw进程将数据块写入数据文件(如checkpoint后)。

(一)准备

1.创建两个表。

SQL> create table aa(id number(4),name varchar2(5));

SQL> create table bb(id number(4),name varchar2(5));

2.aa表中插入数据

SQL> insert into aa values(1,'aa');

SQL> insert into aa values(2,'bb');

SQL> insert into aa values(3,'cc');

SQL> insert into aa values(4,'dd');

SQL> commit;

 

3.查看这些数据所在的数据块,可以看到这四条记录都位于文件4的463块上

SQL> select dbms_rowid.rowid_relative-fno(rowid),dbms_rowid.rowid_block_number(rowid) from aa;

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

                                   4                                  463

                                   4                                  463

                                   4                                  463

                                   4                                  463

4.清空缓冲区,通过重新启动数据库来实现。使用alter system flush buffer cache不能完整清空。

SQL> shutdown immediate;

SQL> startup

5.查看缓冲区内aa、bb的数据块,可以看到这时缓冲区没有这两个表的数据块

SQL> select file#,block# from v$bh where objd=(select object_id from user_object

s where object_name='AA');

未选定行

SQL> select file#,block# from v$bh where objd=(select object_id from user_object

s where object_name='BB');

未选定行

5.再次查看aa记录所在的数据块

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

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

                                   4                                  463

                                   4                                  463

                                   4                                  463

                                   4                                  463

6.由于上一个查询操作,现在可以看到aa的数据块463和其它信息块已经读入缓存,bb也可类似查询。

SQL> select file#,block# from v$bh where objd=(select object_id from user_object

s where object_name='AA');

    FILE#     BLOCK#

    4        461

    4        464

    4        459

    4        459

    4        462

    4        460

    4        463

SQL> select file#,block# from v$bh where objd=(select object_id from user_object

s where object_name='BB');

     FILE#     BLOCK#

    4        467

    4        467

7.通过alter system dump datafile 4 block 467,可以看到这是bb的块头,且高水位为468,使用了3个块。

...

frmt: 0x02 chkval: 0x6632 type: 0x23=PAGETABLE SEGMENT HEADER

Hex dump of block: st=0, typ_found=1

Extent Header:: spare1: 0      spare2: 0      #extents: 1      #blocks: 8    

                  last map  0x00000000  #maps: 0      offset: 2716 

      Highwater::  0x010001d4  ext#: 0      blk#: 3      ext size: 8    

(二)直接路径插入

1、直接插入

SQL> insert into BB select * from aa;

SQL> commit;

2、查询,可以看到,bb的数据块468并没有在缓存中:

SQL> select file#,block# from v$bh where objd=(select object_id from user_object

s where object_name='BB');

     FILE#     BLOCK#

         4        467

         4        467

         4        465

SQL> select dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(r

owid) from BB;

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

                                   4                                  468

3、465块通过dump出来看,是‘FIRST LEVEL BITMAP BLOCK’,也就是段自动管理使用的位图块L1,这是因为插入数据后要更新位图块信息。而467块显示该segment已用块数变为4;

465 dump:

...

frmt: 0x02 chkval: 0x0000 type: 0x20=FIRST LEVEL BITMAP BLOCK

Hex dump of block: st=0, typ_found=1

467 dump:

 ...

frmt: 0x02 chkval: 0x0000 type: 0x23=PAGETABLE SEGMENT HEADER

Hex dump of block: st=0, typ_found=1

Extent Header:: spare1: 0      spare2: 0      #extents: 1      #blocks: 8    

                  last map  0x00000000  #maps: 0      offset: 2716 

      Highwater::  0x010001d5  ext#: 0      blk#: 4      ext size: 8    

(二)间接路径插入

1、间接插入

SQL> insert into BB select * from aa;

SQL> commit;

2、查看

SQL> select file#,block# from v$bh where objd=(select object_id from user_object

s where object_name='BB');

     FILE#     BLOCK#

     4        469

     4        472

     4        467

     4        467

     4        470

     4        465

     4        468

     4        471

     4        466

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

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

                                   4                                  468

                                   4                                  468

                                   4                                  468

                                   4                                  468

                                   4                                  472

                                   4                                  472

                                   4                                  472

                                   4                                  472

可以看到,bb的数据块468,472都已经在缓存中

3、 dump 467

...

      Highwater::  0x010001d9  ext#: 0      blk#: 8      ext size: 8     

... 

  #blocks in seg. hdr's freelists: 0    

  #blocks below: 8    

  mapblk  0x00000000  offset: 0    

  Level 1 BMB for High HWM block: 0x010001d1

  Level 1 BMB for Low HWM block: 0x010001d1

  Segment Type: 1 nl2: 1      blksz: 8192   fbsz: 0     

  L2 Array start offset:  0x00001434

  First Level 3 BMB:  0x00000000

  L2 Hint for inserts:  0x010001d2

  Last Level 1 BMB:  0x010001d1

  Last Level II BMB:  0x010001d2

  Last Level III BMB:  0x00000000

     Map Header:: next  0x00000000  #extents: 1    obj#: 52657  flag: 0x10000000

  Inc # 0

  Extent Map

   0x010001d1  length: 8    

    Auxillary Map

   Extent 0     :  L1 dba:  0x010001d1 Data dba:  0x010001d4

     Second Level Bitmap block DBAs

  高水位变为473,已用块变为8,bmb L1 地址 0x010001d1(file 4,block 465), bmb  L2 地址 0x010001d2(file 4,block 466),数据块开始位置0x010001d4(file 4,block 468)





本文转自 vfast_chenxy 51CTO博客,原文链接:http://blog.51cto.com/chenxy/743909,如需转载请自行联系原作者
目录
相关文章
|
5月前
|
存储 监控 Oracle
关系型数据库Oracle空间不足
【7月更文挑战第15天】
65 6
|
5月前
|
存储 Oracle 关系型数据库
关系型数据库Oracle 空间不足
【7月更文挑战第16天】
63 2
|
7月前
|
存储 数据库
发现oracle10gSYSAUX空间没有了进行处理
发现oracle10gSYSAUX空间没有了进行处理
44 0
|
Oracle 关系型数据库 5G
Oracle 12C rman备份占用大量临时表空间
Oracle 12C rman备份占用大量临时表空间
476 0
|
SQL 存储 Oracle
Oracle-临时表空间(组)解读
Oracle-临时表空间(组)解读
548 0
|
Oracle 关系型数据库
oracle删除表空间、用户
oracle删除表空间、用户
218 0
|
Oracle 关系型数据库
oracle创建表空间
oracle创建表空间
|
存储 SQL Oracle
Oracle-临时表空间和临时表空间组
Oracle数据库中的临时表空间
306 0
Oracle-临时表空间和临时表空间组
|
Oracle 关系型数据库 数据安全/隐私保护
Oracle 创建表空间和表
学习了解Oracle 创建表空间和表。
223 0
|
Oracle 关系型数据库
oracle学习47-oracle删除非空表空间
oracle学习47-oracle删除非空表空间
120 0