Oracle 段(segment), 區(extent), 塊(block) (轉貼)

Oracle 段(segment), 區(extent), 塊(block) (轉貼)

轉貼:http://hi.baidu.com/bystander1983/item/7766d150452af1938d12ed3d

Data blocks ,Extents,Segment     這就是他們之間的邏輯結構。    先看Data blocks(也叫邏輯塊,oracle塊,頁)吧,oracle存儲數據都是在這些數據塊中,一個數據塊是磁盤上數據庫物理空間一系列物理字節的組成。   比Data blocks更高一層的邏輯數據塊空間是extent,一個extent是由一系列臨近的存儲信息的數據塊組成。    最高一層的邏輯結構是segment,一個segment是同一表空間extents的一個集合。每一個segment有不同的數據結構。如每一個表的數據就存儲在自己的data segment,每一個索引存儲在自己的索引段,如果表或者索引是是分區存儲的,那麼每一個分區都存儲在他們各自的segment中。一個segment和他所有的extent都是在一個表空間中,並且一個segment可以跨越幾個數據文件。。

    對於數據庫來說,data block是oracle數據庫中分配和私用的最小存儲單元。但這僅僅對數據庫來說,在物理層次,操作系統層次,所有的數據仍舊是按字節存儲的。每一個操作系統都有自己的塊尺寸(block size),在oracle數據庫中,數據塊的大小都有參數db_block_size在創建數據庫的時候來確定,他的數值應該是操作系統塊尺寸的整數倍。
    數據塊都有這麼幾部分組成,塊頭部分,表目錄,行目錄,空閒空間,數據這幾部分組成。塊頭主要包含兩部分信息:塊頭地址和segment的類型,是數據表還是索引;表目錄主要包含塊中有多少行數據。行目錄主要包含每一行的物理地址。數據就很明顯了,就是這個塊包含的數據。這裡邊最奇妙的就是這個空閒空間,它主要目的就是為varchar這個數據類型準備的,有兩個閾值參數​​pctfree,pctused來控制此數據快移向那一個鍊錶,這兩個參數的設定主要目的是為了避免行連接與行遷移,具體的又夠一篇文章了,以後再寫,^_^。
    在來說extent這個由一系列連續的data blocks組成。每當在數據庫中創建一個表,那麼分配給表的data segment分配一個包含若干數據庫的初始的extent,雖然還沒有插進去數據,但初始的extent已經做好了插入數據的準備。如果初始的extent中的數據塊已經滿了,或者沒有空間插入數據,那麼他將會增量擴展。當然這只是對於串行執行的情況,對於並發就不合適了。一些存儲參數控制著oracle如何為每個段分配可用空間。當你使用create table創建一個表的時候,存儲參數會將決定分配多少的可用空間或者限制此表最多可包含多少個extents,如果在創建表的時候沒有定義這些參數,那麼將採用表空間定義的默認的存儲參數。對於插入和刪除都很頻繁的表,DBA可以通過這個語句來收回無用的extent ,aler table table_name deallocate unused;

    下面來說segment,每一個segment都是一個表空間下有一系列extent組成的邏輯存儲結構。如:當數據庫用戶創建一個表,那麼oracle將分配一個或多個extent來組成表的數據段,創建一個索引,oracle也會紛紛extent給索引數據。一般可以分為data segment,index segment,temporary segment。
    當你創建一個非分區並且非聚焦表的時候,或者一個分區表的一個分區,多個表合用的一個聚簇,都將是一個oracle將處理數據的單個data segment。
    而一個index segment ,對於非分區索引,就是create index創建的索引就會分配一個segment來處理數據;分區索引則對每一個分區分配一個segment來處理數據。
    當一個進程查詢的時候,oracle常常需要一個臨時的工作區存放sql的解析和執行的中間狀態,oracle自動分配的磁盤空間temporary segment。特別當內存的排序區不足時,oracle將會分配一個temporary segment。有時候,下面一些語句有時候需要用到temporary segment:
    create index ....
    select .... order by ;
    select distinct ....
    select ...... group by
    select ...... union
    select ...... intersect
    select ...... minus
    還有就是對一個子查詢來說也會用到temporary segment。如果一個查詢包含distinct子句,一個order by ,一個group by,那麼就需要兩個temporary segment。當創建一個臨時表或索引,oracle也會分配一些temporary segment。
    對於temporary segment,oracle只是在一個用戶的會話(session)中分配,但sql語句執行結束或者會話斷開,將釋放所有的temporary segment。分配這些temporary segment的磁盤空間都是在臨時表空間,如果沒有定義臨時表空間,那麼默認的臨時表空間將是system表空間。對於DBA來說,由於分配和釋放這些temporary segment將非常頻繁,所以至少要定義一個temporary segment,這樣可以避免system表空間的碎片。對於臨時表來說,如果多個會話公用一個臨時表,那麼知道所有的會話全部結束,那才會釋放這個臨時表分配的temporary segment。