表空間是一種爲段(表,索引等)提供空間的邏輯結構,因此,當在表空間中增長,刪除段的時候,數據庫就必須跟蹤這些空間的使用。
以下例所示,假定一個新建立的表空間包含了五個表
表一……表二……表三……表四……表五……未用空間
當咱們刪除表四的時候,就有以下結果
表一……表二……表三……空閒空間段……表五……未用空間
很明顯,ORACLE須要有一個機制來管理表空間中各數據文件的這些分配的或未分配的空間,爲了跟蹤這些可使用的空間(包括未分配使用的和能夠重複使用的),
對於每個空間,咱們必須知道:
一、這個可用空間位於什麼數據文件
二、這個空間的尺寸是多大
三、若是它在用了,是哪個段佔用的這個空間
直到8i以前,全部的表空間都是採用字典管理模式,爲了確保能保存以上的信息,ORACLE用了兩個數據字典表:UET$(已使用的區間)或FET$(空閒空間):
SQL> desc UET$
Name Null? Type
SEGFILE# NOT NULL NUMBER
SEGBLOCK# NOT NULL NUMBER | The segment that uses this space
EXT# NOT NULL NUMBER
TS# NOT NULL NUMBER | The tablespace ID and the file
FILE# NOT NULL NUMBER | ID for that tablespace
BLOCK# NOT NULL NUMBER
LENGTH NOT NULL NUMBER | The location and size of the chunk
SQL> desc FET$
Name Null? Type
TS# NOT NULL NUMBER | The tablespace ID and the file
FILE# NOT NULL NUMBER | ID for that tablespace
BLOCK# NOT NULL NUMBER
LENGTH NOT NULL NUMBER | The location and size of the chunk
查詢該表能夠看到,每一個使用空間或空閒空間(不必定是一個extent,能夠是多個extent)都在該表中對應了一行。它的工做方式是當一個段
被刪除的時候,ORACLE就移動UET$中相應的行到FET$,這個過程的發生是連續的,並且可能發生等待。當併發性很高的時候,數據字典的爭用
就來了。
另外有一個問題就是,當表的空間很不連續或表空間有大量的碎片引發這兩個表的增大,那麼也就會引發數據庫性能上的降低。
本地管理表空間正是爲了解決這一問題來的,在表空間的空間管理上,ORACLE將存儲信息保存在表空間的頭部的位圖中,而不是保存在數據字典中。
經過這樣的方式,在分配回收空間的時候,表空間就能夠獨立的完成操做也不用與其它對象關係。
下面就讓咱們進入到本地管理表空間的內部,看看ORACLE是怎麼實現這一工做的。
Uniform方式的本地管理表空間
一、 先建立了一個本地管理的表空間,區間統一大小分配爲64K
SQL> create tablespace demo
datafile '/ora01/oem/oemdemo01.dbf' size 10m
extent management local uniform size 64k;
二、 在該表空間中建立一個表
SQL>create table demotab ( x number ) tablespace demo
storage ( initial 1000K next 1000k );
咱們經過查詢該表
SQL> select t.table_name,t.initial_extent,t.next_extent from user_tables t where t.table_name = 'DEMOTAB';
TABLE_NAME INITIAL_EXTENT NEXT_EXTENT
DEMOTAB 1024000 65536
能夠發現,該表的存儲參數並非咱們指定的參數INITIAL_EXTENT,而是uniform size的整數倍,NEXT_EXTENT則等於uniform size。咱們從該
查詢就也能夠看到以下狀況
SQL>select count(*) from user_extents where segment_name = 'DEMOTAB';
COUNT(*)
16
也就是說,該表在該表空間中已經存在16個extent,而不是一個extent(這是與字典管理的差異,若是是字典管理的表空間,若是建立以上的表,該查詢的結果是1)。
三、 獲取該數據文件的文件ID
SQL> col name format a30 trunc
SQL> select file#, name from v$datafile;
File# NAME
-----
1 /oras1/oem/oemsystem01.dbf
2 /oras3/oem/oemundo01.dbf
3 /ora01/oem/oemoem_repository01
4 /ora01/oem/oemrcat01.dbf
5 /ora01/oem/oemdemo01.dbf
咱們能夠檢查uet$與fet$
SQL> select count(*) from uet$ where file# = 5;
COUNT(*)
0
SQL> select count(*) from fet$ where file# = 5;
COUNT(*)
0
四、 能夠看到,ORACLE沒有在這兩個表中保存任何信息,如今咱們dump該數據文件的第三個塊。
SQL> alter system dump datafile 5 block 3;
System altered.
查看DUMP文件,有以下信息
Start dump data blocks tsn: 5 file#: 5 minblk 3 maxblk 3
buffer tsn: 5 rdba: 0x01400003 (5/3)
scn: 0x0000.202f7a6f seq: 0x01 flg: 0x00 tail: 0x7a6f1e01
frmt: 0x02 chkval: 0x0000 type: 0x1e=KTFB Bitmapped File Space Bitmap
File Space Bitmap Block:
BitMap Control:
RelFno: 5, BeginBlock: 9, Flag: 0, First: 16, Free: 63472
FFFF000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
.....
注意其中的FFFF00,,這是16進制的表現方法,咱們轉換爲二進制,有
1111,1111,1111,1111,0000,0000
發現這裏有16個1,每個1就是一個位(bit),表明64K,也就表明了該表空間有已經分配了的16個extent,若是咱們將該表擴展,將又有什麼
結果呢?
SQL> alter table demotab allocate extent;
Table altered.
SQL> alter table demotab allocate extent;
Table altered.
SQL> alter table demotab allocate extent;
Table altered.
這樣以後,咱們應該有19個extent了,再dump第三個塊
Start dump data blocks tsn: 5 file#: 5 minblk 3 maxblk 3
buffer tsn: 5 rdba: 0x01400003 (5/3)
scn: 0x0000.202f7c64 seq: 0x01 flg: 0x00 tail: 0x7c641e01
frmt: 0x02 chkval: 0x0000 type: 0x1e=KTFB Bitmapped File Space Bitmap
File Space Bitmap Block:
BitMap Control:
RelFno: 5, BeginBlock: 9, Flag: 0, First: 19, Free: 63469
FFFF07 0000000000 0000000000000000 0000000000000000 0000000000000000
除了之前的FFFF,如今多了07,怎麼解釋呢?
07轉換爲二進制爲0000,0111,可是仍是不夠解釋以上的狀況,這裏咱們沒有考慮到字節交換的狀況,由於以上FF交換後仍是FF,可是若是是07
,咱們就必須考慮字節交換(由於計算機是一個字節一個字節的寫,一個字節佔兩位固然是先寫後面了,如從01到0F到FF爲止。若是咱們明白
了,那麼FFFF07轉換爲二進制爲 1111,1111,1111,1111,0000,0111。
每一個字節交換得
1111,1111,1111,1111,1110,0000
能夠發現,這裏有19個1,也就是19個位(bit),表明瞭如今的19個extent。
五、 一樣咱們dump該數據文件第9個塊,則有
Start dump data blocks tsn: 5 file#: 5 minblk 9 maxblk 9
buffer tsn: 5 rdba: 0x01400003 (5/3)
scn: 0x0000.202f7c64 seq: 0x01 flg: 0x00 tail: 0x7c641e01
frmt: 0x02 chkval: 0x0000 type: 0x1e=KTFB Bitmapped File Space Bitmap
Extent Control Header
Extent Header:: spare1: 0 space2: 0 #extents: 16 #blocks: 127
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x01c0000a ext#: 0 blk#: 0 ext size: 7
#blocks in seg. hdr's freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
Disk Lock:: Locked by scn: 0x0006.012.00000017
Map Header:: next 0x00000000 #extents: 16 obj#: 3090 flag: 0x40000000
Extent Map
0x01c0000a length: 7
0x01c00011 length: 8
0x01c00019 length: 8
0x01c00021 length: 8
0x01c00029 length: 8
0x01c00031 length: 8
0x01c00039 length: 8
0x01c00041 length: 8
0x01c00049 length: 8
0x01c00051 length: 8
0x01c00059 length: 8
0x01c00061 length: 8
0x01c00069 length: 8
0x01c00071 length: 8
0x01c00079 length: 8
0x01c00081 length: 8
nfl = 1, nfb = 1 typ = 1 nxf = 0
SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000 End dump data blocks tsn: 5 file#: 5 minblk 9 maxblk 9
這是該數據文件中表DEMOTAB的表頭(一個塊)信息,從這裏能夠看到,該表從第9個塊開始使用Highwater:: 0x01c0000a已是第10個塊了,從以上列表,咱們也能清楚的看到,該表耗費了16個區間。
因爲該表是數據文件的第一個表,因此位圖區佔用從3到8共6個塊,加上前面兩個文件頭,也就是說,在數據文件頭部共8個塊用於系統消耗。
若是咱們的db_block_size爲8192,那麼很明顯,佔用的空間爲64K(注意:對於不一樣的塊大小,文件頭部的塊個數與大小可能會不同)。
也由於僅僅操做數據文件頭部幾個塊,不用操做數據字典,因此ORACLE在本地管理的表空間中添加,刪除段的時候,效率要比字典管理的表空間快。特別是在併發性很強的空間請求中。
ORACLE經過強制性的手段使本地管理表空間中的全部Extent是一樣大小的,儘管你可能自定義了不一樣的存儲參數。
六、 補充一些字典管理表空間的不一樣
a. 若是是字典管理,表空間中的表的區間的大小取決於表的存儲參數,若是沒有定義,則取表空間的通用存儲參數。因此每一個表的區間大小能夠不同。
b. 若是不指定表的最少區間數,那麼默認建立的時候,該表只有一個區間,而不是多個區間。
c. 字典管理的文件頭只佔用一個塊,第一個表的HWM應當是Highwater:: x01c00003,關於這個能夠本身dump該數據文件查看。
Autoallocate的本地管理表空間
在自動分配的本地管理的表空間中,區間尺寸可能由如下尺寸組成64k, 1m, 8m, 64m 甚至是256m。可是無論多大,都有一個通用尺寸64k,因此64K就是該表空間的位大小。
SQL> create tablespace dummy
datafile 'c:\dummy01.dbf' size 100m
autoallocate;
Tablespace created.
SQL> create table x1 (x number)
tablespace dummy
storage (initial 50M);
Table created.
SQL> select file# from v$datafile where name like '%DUMMY%';
FILE#
12
SQL> select extents from user_segments
where segment_name = 'X1' ;
EXTENTS
50
SQL> alter system dump datafile 12 block 3;
System altered.
*** SESSION ID11.59) 2002-11-22 10:37:35.000
Start dump data blocks tsn: 19 file#: 12 minblk 3 maxblk 3
buffer tsn: 19 rdba: 0x03000003 (12/3)
scn: 0x0000.00f2959b seq: 0x01 flg: 0x00 tail: 0x959b1e01
frmt: 0x02 chkval: 0x0000 type: 0x1e=KTFB Bitmapped File Space Bitmap
File Space Bitmap Block:
BitMap Control:
RelFno: 12, BeginBlock: 9, Flag: 0, First: 800, Free: 62688
FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
FFFFFFFF00000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
能夠看到該表實際只有50個區間(extent),可是有800個位(bit)
50*1024=800*64
還能夠看出,位大小並不等於extent大小。