關於Oracle塊的一些總結

regonly1發表於2009-09-15

以下關於Oracle的一些描述都是個人總結而成,由於個人知識的限制,在本地管理表空間部分及dump資料塊的部分的描述在某些方面會不準確,與實際情況不符合。
Oracle的表空間由若干的資料檔案(OS級)所組成。一個表空間最多可以有1024個資料檔案組成。
資料檔案的大小受塊大小的限制可以有不同的大小。假設一個塊大小為8k。
8i後的rowid組成結構如下:OOOOOO FFF BBBBBB RRR
共有10個位元組組成(1位元組×10=8bit×10=80bit)
OOOOOO是data_object_id(32bit)
FFF是rfile#(10bit)
BBBBBB是block_id(22bit)
RRR是row_id(16bit)
因此可以看到對應的rowid可以表示的最大檔案數為2^10=1024,每個檔案可表示的最大的block數為2^22=4194304 假設每個block size=8k,則有8*1024*2^22/1024/1024/1024 = 32G,即如果block的大小為8k,則一個資料檔案的最大大小為32G。由於一個表空間最多有1024個資料檔案,則一個塊大小為8k的表空間最大可以為32T。
計算公式:
select "block_size(K)", "block_size(K)" * block_num / 1024 / 1024 "file_size(G)"
  from (select power(2, rownum) "block_size(K)", power(2, 22) block_num
          from dual
        connect by rownum <= 4)
以上說明的都只是smallfile tablespace, Oracle 10g開始還支援一種bigfile tablespace。這種表空間只能有一個資料檔案,該資料檔案最大可以達到4G個block大小。
理論上的 BFT 可以達到下面所列的值:
資料塊大小(單位:K) BFT 最大值(單位:T)
2k                      8T
4k                      16T
8k                      32T
16k                     64T
32k                     128T
預設情況下建立的表空間都是smallfile表空間。要建立大檔案表空間,則可以透過指定bigfile引數來指定。
檢視當前表空間的預設建立型別,可以透過下面查詢來檢視:
select * from database_properties dp where dp.property_name = 'DEFAULT_TBS_TYPE'

下面介紹表空間的邏輯組成
一個表空間在邏輯上是由若干個segment組成的,每個segment都對應一個object。但是並不是每個object都對應一個segment,如果function、procedure等。每個segment由若干extent組成,extent是Oracle分配空間的最小單位,當segment需要擴充套件時,oracle就會為該segment分配新的extent。分配extent的大小由建立表空間時uniform. size引數指定。如果指定,則每次按照指定的大小進行擴充套件。如果不指定,則以pctincrease引數指定的比例逐級遞增。每個extent都由若干個塊組成,塊的多少取決於分配的extent的大小。假設一個extent為1m,則含有的block數為:1*1024/8=128個。
本地管理表空間(local management tablespace)下,每個segment的前3個塊都用於存放該段的儲存資訊。每個資料檔案的前8個塊都是存放所有段的資訊:
建立表空間:
create tablespace mytbs datafile 'E:\oracle\oradata\lyon\mytbs01.dbf'
size 10m uniform. size 1m extent management local segment space management auto;
在指定的表空間上建立測試表:
create table mytb(x varchar2(10), y varchar2(30)) tablespace mytbs nologging;
建立測試資料:
insert into mytb(x, y)
select 'This', dump('This',16) from dual union all
select 'is', dump('is',16) from dual union all
select 'a', dump('a',16) from dual union all
select 'dump', dump('dump',16) from dual union all
select 'test', dump('test',16) from dual union all
select '!', dump('!',16) from dual;
commit;
檢視該表的extent資訊:
select segment_name, tablespace_name, file_id, block_id, bytes, blocks
 from dba_extents de
where de.segment_name = 'MYTB';
> select segment_name, tablespace_name, file_id, block_id, bytes, blocks
  2   from dba_extents de
  3  where de.segment_name = 'MYTB';

SEGMENT_NAME                   TABLESPACE_NAME                   FILE_ID   BLOCK_ID      BYTES     BLOCKS
------------------------------ ------------------------------ ---------- ---------- ---------- ----------
MYTB                           MYTBS                                  21          9    1048576        128

已用時間:  00: 00: 00.32

可以看到block_id=9,且共有128個塊。
檢視當前實際資料所在的塊:
customer21@ORCL> select dbms_rowid.rowid_relative_fno(rowid) rfile#,
  2         dbms_rowid.rowid_block_number(rowid) blknumber,
  3         dbms_rowid.rowid_row_number(rowid) rownumber
  4    from mytb;

    RFILE#  BLKNUMBER  ROWNUMBER
---------- ---------- ----------
        21         35          0
        21         35          1
        21         35          2
        21         35          3
        21         35          4
        21         35          5

已選擇6行。

已用時間:  00: 00: 00.03
可以看到實際資料開始使用的塊為35。
有兩個問題:
1、新的表空間下建立的物件,實際object開始的塊的id為9,前面的8個塊呢?
2、該物件(表mytb),在表空間中開始分配的block_id=9,但是為何初始資料所在的塊為35?
第一個問題比較容易回答,這8個塊是本地管理表空間(LMT)情況下,用於存放物件資訊的。
第二個問題實際相差了35-9=26個塊。除去兩端的塊,還有24個塊去哪裡了?

ORACLE中空閒資料塊可以透過FREELIST或BITMAP來維護,它們位於一個段的頭部用來標識當前段中哪些資料塊可以進行INSERT。在本地管理表空間中ORACLE自動管理分配給段的區的大小,只在本地管理的表空間中才能選用段自動管理,採用自動段空間管理的本地管理表空間中的段中的空閒資料塊的資訊就存放在段中某些區的頭部,使用點陣圖來管理(最普通的情況是一個段的第一個區的第一個塊為FIRST LEVEL BITMAP BLOCK,第二個塊為SECOND LEVEL BITMAP BLOCK,第三個塊為PAGETABLE SEGMENT HEADER 
也就是說,每個段的第一個區的前面三個塊都是存放空閒資料庫資訊的。那還剩下24-3=21個塊。
alter system dump datafile 21 block min 12 block max 34
alter system dump datafile 21 block 35
dump 35號塊,取出一段如下:
col  0: [ 4]  54 68 69 73
這個與
select * from mytb
Typ=96 Len=4: 54,68,69,73的結果是一樣的。
說明了這個值的長度為4,每個位元組對應的acsii碼是54,68,69,73(16進位制),轉換為字元即為:This。
drop index idx_mytb_x
create index idx_mytb_x on mytb(x) tablespace mytbs nologging;
select * from dba_extents de where de.segment_name = 'IDX_MYTB_X'
alter system dump datafile 21 block 141
索引dump資訊
row#0[8025] flag: ------, lock: 0, len=11
col 0; len 1; (1):  21
col 1; len 6; (6):  05 40 00 23 00 05
row#1[8011] flag: ------, lock: 0, len=14
col 0; len 4; (4):  54 68 69 73
col 1; len 6; (6):  05 40 00 23 00 00
row#2[8000] flag: ------, lock: 0, len=11
col 0; len 1; (1):  61
col 1; len 6; (6):  05 40 00 23 00 02
row#3[7986] flag: ------, lock: 0, len=14
col 0; len 4; (4):  64 75 6d 70
col 1; len 6; (6):  05 40 00 23 00 03
row#4[7974] flag: ------, lock: 0, len=12
col 0; len 2; (2):  69 73
col 1; len 6; (6):  05 40 00 23 00 01
row#5[7960] flag: ------, lock: 0, len=14
col 0; len 4; (4):  74 65 73 74
col 1; len 6; (6):  05 40 00 23 00 04

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12932950/viewspace-614688/,如需轉載,請註明出處,否則將追究法律責任。

相關文章