Oracle中的段
Oracle的體系結構中,關於儲存結構大家應該都很熟悉了。
估計下面這張圖大家都看得熟悉的不能再熟悉了。
簡單來說,裡面的一個重要概念就是段,如果是開發同學,可能每次聽到這裡都會有些模糊,好像懂,好像不懂。n年前給開發同學內部培訓的時候,有開發同事就百思不得其解,我當時按照書上的原話也沒有收服它們,同樣的話出自DBA的口中似乎多了一些信服的味道。多年之後,還有同學問起我這個問題的時候,讓我想起了曾經苦苦學習Oracle的那些時光,我簡單說說我的理解。
首先老三篇的內容我們換一種玩法,如果是一個11gR2的預設資料庫環境,下面的這個語句會建立幾個段。
create table test_seg (id number primary key,name varchar2(30),memo clob);
這個問題問住了不少的人,而似乎我也聽到了不少意料之中的答案,如果認為是1個的,就是理解建立了一個表,那就是一個段了,這個段型別是TABLE,如果認為是2個的,那就是看到了裡面有一個主鍵,那就是對應一個索引段,如果認為是3個的,那就是看到了LOB欄位,不過還差一步,LOB其實是會建立兩個段,一個是LOB段,一個是LOB索引段,結構化的資料是Oracle的強項,而如果加入半結構化的資料處理,就得額外花些功夫。而如果我們在11gR2的環境中,我們耳濡目染的而一個特性,延遲段建立,存在一個資料庫引數segment_deferred_creation預設為true,即開啟了延遲段建立,所以上面的語句不會建立任何的段。
SQL> select segment_name,segment_type from user_segments;
no rows selected
而我們插入一部分的資料,我們就插入近50萬資料吧。
insert into test_seg select level,'obj'||level,'' from dual connect by level<500000;
這樣一來,問題就回歸了,是4個段,其中SYS_IL開頭的段是索引段,剩下SYS_開頭的兩個是LOB相關的段。
select segment_name,segment_type from user_segments;
SEGMENT_NAME SEGMENT_TYPE
------------------------------ ------------------------------------
TEST_SEG TABLE
SYS_IL0000089494C00003$$ LOBINDEX
SYS_C0011978 INDEX
SYS_LOB0000089494C00003$$ LOBSEGMENT
怎麼去理解這個段呢。
我們還是求助於user_segments來看看。
SQL> select segment_name,extents,blocks from user_segments
SEGMENT_NAME EXTENTS BLOCKS
------------------------------ ---------- ----------
TEST_SEG 26 1408
SYS_IL0000089494C00003$$ 1 8
SYS_C0011978 23 1024
SYS_LOB0000089494C00003$$ 1 8
可以看到段TEST_SEG存在26個區塊,含有1408個資料塊。這些都是概覽的資訊。
如果想得到更細緻一些的資訊呢,那就是user_extents了。我們簡化一下,只是檢視segment_type為TABLE的區塊資訊。
SQL> select segment_name,segment_type,extent_id,bytes,blocks from user_extents where segment_name='TEST_SEG' order by segment_name,extent_id ;
TEST_SEG TABLE 0 65536 8
TEST_SEG TABLE 1 65536 8
TEST_SEG TABLE 2 65536 8
TEST_SEG TABLE 3 65536 8
TEST_SEG TABLE 4 65536 8
TEST_SEG TABLE 5 65536 8
TEST_SEG TABLE 6 65536 8
TEST_SEG TABLE 7 65536 8
TEST_SEG TABLE 8 65536 8
TEST_SEG TABLE 9 65536 8
TEST_SEG TABLE 10 65536 8
TEST_SEG TABLE 11 65536 8
TEST_SEG TABLE 12 65536 8
TEST_SEG TABLE 13 65536 8
TEST_SEG TABLE 14 65536 8
TEST_SEG TABLE 15 65536 8
TEST_SEG TABLE 16 1048576 128
TEST_SEG TABLE 17 1048576 128
TEST_SEG TABLE 18 1048576 128
TEST_SEG TABLE 19 1048576 128
TEST_SEG TABLE 20 1048576 128
TEST_SEG TABLE 21 1048576 128
TEST_SEG TABLE 22 1048576 128
TEST_SEG TABLE 23 1048576 128
TEST_SEG TABLE 24 1048576 128
TEST_SEG TABLE 25 1048576 128
這裡我們可以看到段級別對應的區是0-25,和user_segments中看到的26個區資料是一致的。
而這些區塊的ID其實就是一個邏輯的編號,是基於段級別的劃分。
同樣上面的語句,我們簡單改一下,檢視segment_type為INDEX的區塊資訊。如下:
SEGMENT_NAME SEGMENT_TYPE EXTENT_ID BYTES BLOCKS
-------------------- -------------------- ---------- ---------- ----------
SYS_C0011978 INDEX 0 65536 8
SYS_C0011978 INDEX 1 65536 8
SYS_C0011978 INDEX 2 65536 8
SYS_C0011978 INDEX 3 65536 8
SYS_C0011978 INDEX 4 65536 8
SYS_C0011978 INDEX 5 65536 8
SYS_C0011978 INDEX 6 65536 8
SYS_C0011978 INDEX 7 65536 8
可以很明顯看到區塊的ID也是從0開始,比如0-7
這裡就需要明白,這裡的區塊0是相對於這個segment_type為INDEX的segment為SYS_C0011978而言的。所以這裡的值是一個相對的值,而不是絕對的。
而絕對的位置怎麼查詢呢,這得依賴於物理結構,能夠定位的一個利器就是ROWID,我們取出1行資料來看看。
SQL> select dbms_rowid.ROWID_RELATIVE_FNO(rowid) as file#,dbms_rowid.ROWID_BLOCK_NUMBER(rowid) as block#,dbms_rowid.ROWID_ROW_NUMBER(rowid) as row#,a.* from test.test_seg a where rownum<2;
FILE# BLOCK# ROW# ID NAME MEMO
---------- ---------- ---------- ---------- -------------------- ----------
4 134803 0 468 obj468
可以看到是4號資料檔案,對應的資料塊是134803
要知道一個資料塊裡存放的資料基本上不是1行資料,而是相關的多行資料。
我們就可以做一個dump來看看。
alter system dump datafile 4 block 134803;
然後檢視 select *from v$diag_info; 來得到trace檔案的路徑。
可以透過trace檔案看到下面的內容:
tab 0, row 0, @0x1f8a
tl: 14 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 3] c2 05 45
col 1: [ 6] 6f 62 6a 34 36 38
tab 0, row 1, @0x1f7c
tl: 14 fb: --H-FL-- lb: 0x1 cc: 2
col 0: [ 3] c2 05 46
col 1: [ 6] 6f 62 6a 34 36 39
目前存在3個欄位,但是因為當前的LOB欄位為空,就直接延遲建立了,只顯示出來了兩個欄位。
而繼續做一個update操作,提交事務。
SQL> update test_seg set memo='aaa' where rownum=1;
commit;
可以透過trace看到裡面的內容已經大大不同,一個最大的變化就是LOB段的延遲建立情況,這個時候修改LOB段資料,所以就會重新初始化。
tab 0, row 0, @0x690
tl: 57 fb: --H-FL-- lb: 0x2 cc: 3
col 0: [ 3] c2 05 45
col 1: [ 6] 6f 62 6a 34 36 38
col 2: [42]
00 54 00 01 02 0c 80 00 00 02 00 00 00 01 00 00 00 12 ef 45 00 16 09 00 00
00 00 00 00 06 00 00 00 00 00 01 00 61 00 61 00 61
LOB
Locator:
Length: 84(42)
Version: 1
Byte Length: 2
LobID: 00.00.00.01.00.00.00.12.ef.45
Flags[ 0x02 0x0c 0x80 0x00 ]:
Type: CLOB
Storage: BasicFile
Enable Storage in Row
Characterset Format: IMPLICIT
Partitioned Table: No
Options: VaringWidthReadWrite
Inode:
Size: 22
Flag: 0x09 [ Valid DataInRow ]
Future: 0x00 (should be '0x00')
Blocks: 0
Bytes: 6
Version: 00000.0000000001
Inline data[6]
Dump of memory from 0x00007FBE38B88127 to 0x00007FBE38B8812D
7FBE38B88120 00010000 00610061 02002C61 [....a.a.a,..]
tab 0, row 1, @0x1f7c
tl: 14 fb: --H-FL-- lb: 0x0 cc: 2
col 0: [ 3] c2 05 46
col 1: [ 6] 6f 62 6a 34 36 39
所以對於段來說,裡面的資訊對應的都是邏輯的概念,地址是邏輯地址,是相對的,而非絕對的。切莫認為一個區可以同時屬於多個段。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-2128378/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle表段中的高水位線HWMOracle
- Oracle的回滾段介紹Oracle
- oracle臨時段Oracle
- ORACLE回滾段Oracle
- Oracle之 資料塊、區段和段Oracle
- Oracle資料庫中的段管理方式詳細介紹 (3)Oracle資料庫
- oracle段管理歸納Oracle
- ORACLE回滾段(1)Oracle
- ORACLE回滾段(2)Oracle
- ORACLE回滾段(轉)Oracle
- ORACLE回滾段管理Oracle
- ORACLE 回滾段詳解Oracle
- 轉儲oracle undo段資訊Oracle
- Oracle層次查詢和分析函式在號段選取中的應用Oracle函式
- oracle 11g 回滾段的測試Oracle
- Oracle 時段負載情況Oracle負載
- Oracle啟動三階段(一)Oracle
- Oracle啟動三階段(二)Oracle
- 限定client段ip訪問oracle!clientOracle
- Oracle表段中高水位線HWMOracle
- oracle 段空間管理問題Oracle
- Oracle層次查詢和分析函式在號段選取中的應用(轉)Oracle函式
- Ext 中 如何將grid的資料傳到tab中的html段中HTML
- Oracle 自動段空間管理(ASSM)OracleSSM
- oracle回滾段 undo 表空間Oracle
- ORACLE技術專題-- 回滾段Oracle
- oracle-tom-表和段關係Oracle
- 伺服器ip的A段B段C段的區別伺服器
- assm:Oracle 10g的自動段空間管理SSMOracle 10g
- Oracle 10g的自動段空間管理(ASSM)Oracle 10gSSM
- 關於Oracle8i回退段引起的錯誤Oracle
- Oracle 11gr2 的新特性-延遲段建立Oracle
- 監控Oracle資料庫效能的指令碼段整理Oracle資料庫指令碼
- 【延遲段建立】Oracle 11gR2的延遲段建立(deferred segment creation)特性Oracle
- ORACLE 檢查資料庫表中是否存在不規範字 段的語句參考.sqlOracle資料庫SQL
- CAD繪圖工具中的多段線命令繪圖
- 專案管理中四種常見的階段專案管理
- 如何隱藏網頁中的一段文字網頁