Oracle數據內部的邏輯存儲
?
Oracle存儲數據的最小粒度(finest level of granularity)被稱為數據塊 (data block)(也叫做邏輯塊 (logical block),Oracle塊 (Oracle block)或頁 (page))。一個數據塊對應于磁盤上數個字節(byte)的物理數據庫空間。
處于數據塊之上的邏輯數據庫空間是數據擴展 (extent)。數據擴展是為存儲數據而分配的一組連續的數據塊。
位于數據擴展之上的邏輯數據庫存儲結構是段 (segment)。段由一組數據擴展 (extent)構成,這些數據擴展位于同一表空間(tablespace)中,用于存儲各種邏輯數據結構。例如每個表(table)的數據都存儲在其自身的數據段 (data segment)中,每個索引(index)的數據都存儲在其自身的索引段 (index segment)中。如果表或索引是分區存儲(partitioned)的,則每個分區擁有自己的段。
Oracle為段(segment)分配空間時以數據擴展(extent)為單位。當段內已有的數據擴展沒有可用空間時,Oracle為此段分配一個新的數據擴展。因為數據擴展是隨需分配的,所以一個段內的數據擴展在磁盤上未必是連續的。
這三者直接的關系如下圖
?
一個段(segment)以及屬于她的所有數據擴展(extent)必須包含在同一表空間中。但在一個表空間內,屬于同一個段的數據擴展可以分布在多個數據文件(datafile)上,即段可以跨文件存儲。但是每個數據擴展只能包含于同一個數據文件中。
在用戶分配一個新的數據擴展(extent)時,其中的數據塊(data block)未必被同時分配。如果用戶是為某個數據庫對象分配數據擴展 ,那么數據塊也同時被立即分配并加入可用塊列表(free list)中。如果數據擴展并非專為某數據庫對象分配,那么數據塊只在 高水位線 ? (high water mark)移動時才被分配。高水位線是段(segment)中已用和未用空間的邊界。
數據塊概述
?
Oracle對數據庫數據文件(datafile)中的存儲空間進行管理的單位是數據塊(data block)。數據塊是數據庫中最小的(邏輯)數據單位。與數據塊對應的,所有數據在操作系統級的最小物理存儲單位是字節(byte)。每種操作系統都有一個被稱為塊容量 (block size)的參數。Oracle每次獲取數據時,總是訪問整數個(Oracle)數據塊,而不是按照操作系統塊的容量訪問數據。
數據庫中標準的數據塊(data block)容量是由初始化參數? DB_BLOCK_SIZE ? 指定的。除此之外,用戶還可以指定五個非標準的數據塊容量(nonstandard block size,在10g R2 32bit版本中可以指定2k,4k,16k,32k四個非標準數據塊容量)。數據塊容量應該設為操作系統塊容量的整數倍(同時小于數據塊容量的最大限 制),以便減少不必要的I/O操作。Oracle的數據塊是Oracle可以使用和分配的最小存儲單位。
數據塊結構
在Oracle中,不論數據塊中存儲的是表(table)、索引(index)或簇表(clustered data),其內部結構都是類似的。下圖說明了數據塊的結構

數據塊頭(包含可變內容和標準內容)
標準內容:數據塊頭中包含了此數據塊的概要信息,例如塊地址(block address)及此數據塊所屬的段(segment)的類型,例如,表或索引,該部分為。可變內容:ITL(Interested Transaction List)用來記錄該塊所有發生的事務,一個itl可以看作是一個記錄,在一個時間,可以記錄一個事務(包括提交或者未提交事務)。當然,如果這個事務已 經提交,那么這個itl的位置就可以被反復使用了,因為itl類似記錄,所以,有的時候也叫itl槽位。 如果一個事務一直沒有提交,那么,這個事務將一直占用一個itl槽位,itl里面記錄了事務信息,回滾段的入口,事務類型等等。如果這個事務已經提交,那 么,itl槽位中還保存的有這個事務提交時候的SCN號。
表目錄區
如果一個數據表在此數據塊中儲存了數據行,那么數據表的信息將被記錄在數據塊的表目錄區(table directory)中。
行目錄區
此區域包含數據塊中存儲的數據行的信息(每個數據行片斷(row piece) 在行數據區(row data area)中的地址)。 ? (一個數據塊中可能保存一個完整的數據行,也可能只保存數據行的一部分 ,所以文中使用row piece)
當一個數據塊(data block)的行目錄區(row directory)空間被使用后,即使數據行被刪除(delete),行目錄區空間也不會被回收。舉例來說,當一個曾經包含50條記錄的數據塊被清空 后,其塊頭(header)的行目錄區仍然占用100字節(byte)的空間。只有在數據塊中插入(insert)新數據時,行目錄區空間才會被重新利用。
管理開銷
數據塊頭(data block header),表目錄區(table directory),行目錄區(row directory)被統稱為管理開銷。其中 有些開銷的容量是固定的;而有些開銷的總容量是可變的(ITL)。數據塊中固定及可變管理開銷的容量平均在84到107字節(byte)之間。
行數據
數據塊(data block)中行數據區(row data)包含了表或索引的實際數據。一個數據行可以跨多個數據塊(是行鏈接和行遷移下文會講到)
可用空間
在插入新數據行,或在更新數據行需要更多空間時(例如,原來某行最后一個字段為空(trailing null),現在要更新為非空值),將使用可用空間區(free space)中的空間。
如果一個數據塊(data block)屬于表或簇表的數據段(data segment),或屬于索引的索引段(index segment),那么在其數據塊頭中還可能會存儲事務條目 。如果一個數據塊中的數據行正在由? INSERT, ? UPDATE, ? DELETE,及 SELECT...FOR UPDATE 語句訪問,此數據塊中就需要保存事務條目。
事務條目所需的存儲空間依據操作系統而定。在常見的操作系統中事務條目大約需要占用23字節(byte )。
數據塊中的可用空間管理
數據庫中段的管理方式決定了數據塊中可用空間的管理方式。的可用空間可以被自動管理。段內的可用/已用空間以位圖(bitmap)形式記錄(自動管理模式下),這與手動管理采用free list以列表方式的管理不同。段空間自動管理(Automatic segment-space management)具備以下優勢:
1、空間利用效率更高,尤其針對每行數據容量差異大的表(或其他對象)
2、能夠更好地針對當前數據的情況實時調整
3、易于使用
4、在RAC環境下能更好的提升性能和空間利用(個人認為是因為第一和第二點的優勢在RAC環境下能更明顯的體現出來的原因。)
用戶可以在創建一個本地管理的表空間(locally managed tablespace)時選擇自動段空間管理(automatic segment-space management)功能。這樣在此表空間內創建的段都將默認地設置為自動段空間管理。
數據塊可用空間的有效性及優化
有兩種SQL語句可以增加數據塊中的可用空間:分別是? DELETE ? 語句,和將現有數據值更新為占用容量更小值的? UPDATE 語句。在以下兩種條件下,上述兩中操作釋放的空間可以被后續的? INSERT ? 語句使用:
如果? INSERT ? 語句與上述兩種操作在同一事務(transaction)中,且位于釋放空間的語句之后,那么? INSERT ? 語句可以使用被釋放的空間。
如果? INSERT ? 語句與釋放空間的語句在不同的事務中(比如兩者是由不同的用戶提交的),那么只有在釋放空間的語句提交后,且插入數據必需使用此數據塊時, ? INSERT ? 語句才會使用被釋放的空間。
數據塊(data block)中被釋放出的空間未必與可用空間區(free space)相連續。Oracle在滿足以下條件時才會將釋放的空間合并到可用空間區:(1) ? INSERT ? 或? UPDATE ? 語句選中了一個有足夠可用空間容納新數據的數據塊,(2)但是此塊中的可用空間不連續,數據無法被寫入到數據塊中連續的空間里。Oracle只在 滿足上述條件時才對數據塊中的可用空間進行合并,這樣做是為了避免過于頻繁的空間合并工作影響數據庫性能。
數據塊中行片段
Oracle 使用一個或多個行片斷(row piece)來存儲表的每一行數據的前255列。當一個數據塊(data block)可以容納一個完整的數據行時(且表的列數小于等于 256),那么此行就可以使用一個行片斷來存儲。當插入(insert)一個數據行,或更新(update)已有數據行時,數據行容量大于數據塊容量,那么 Oracle 將使用多個行片斷來存儲此行。大多數情況下,每個數據行只存儲于一個行片斷中,且在同一數據塊內。
有兩種情況會導致表中某行數據過大,一個數據塊(data block)無法容納。
第一種情況,行鏈接
當一行數據被插入時一個數據塊就無法容納 ? 。在這種情況下Oracle將這行數據存儲在段內的一個數據塊鏈 (chain)中。在插入數據量大的行時常會發生行鏈接(row chaining),例如一個包含數據類型為? LONG ? 或? LONG RAW? 列的數據行。此時行鏈接不可避免。當 Oracle 必須使用多個行片斷來存儲同一數據行時(且每個行片斷位于不同的數據塊內),此行將在多個數據塊間構成行鏈接 (Row Chaining)。
當一個表超過 255 列時,每行第255列之后的數據將作為一個新的行片斷(row piece)存儲在相同的數據塊(data block)中,這被稱為塊內鏈接 (intra-block chaining)。由多個行片斷組成的行進行塊內鏈接時,使用各行片斷的 rowid 進行鏈接。當一個行為塊內鏈接時,用戶可以從同一數據塊中訪問此行的全部數據。如果一個數據行位于同一數據塊內,那么訪問此行不會影響 I/O 性能,因為訪問此行不會帶來額外的 I/O 開銷。
行遷移
原本存儲在一個數據塊(data block)內的數據行,因為更新操作導致長度增長,而所在數據塊的可用空間也不能容納增長后的數據行 ? 。在這種情況下,Oracle將此行數據遷移到新的數據塊中。Oracle在被遷移數據行原來所在位置保存一個指向新數據塊的指針。被遷移數據行的 rowid 保持不變。
當數據行發生鏈接(chain)或遷移(migrate)時,對其訪問將會造成 I/O 性能降低,因為Oracle為獲取這些數據行的數據時,必須訪問更多的數據塊(data block)。
PCTUSED、PCTFREE
在手動管理的表空間(manually managed tablespaces)中,用戶可以使用? PCTFREE ? 和? PCTUSED? 這兩個存儲管理參數來控制對某段(segment)進行插入和更新操作時,如何利用屬于此段的數據塊(data block)中的可用空間。用戶也可以在創建或修改索引時為其設定? PCTFREE ? 參數(索引存儲在索引段(index segment)中)。
PCTFREE
PCTFREE ? 參數用來設置一個數據塊(data block)中至少需要保留 (reserve)多少可用空間(百分比值),為數據塊中已有數據更新時可能發生的數據量增長做準備。例如,當用戶用 ? CREATE TABLE ? 語句創建表時指定了以下參數: ? PCTFREE 20。
這個參數設定了此表對應的數據段(data segment)中的每個數據塊(data block)至少保留20%的可用空間,以備塊中已有數據更新時使用。只要數據塊中行數據區與數據塊頭的容量之和不超過數據塊總容量的80%,用戶就可以向其中插入新數據,數據行被放入行數據區(row data area),相關信息被寫入數據塊頭(overhead area)。下圖說明了? PCTFREE ? 的作用。
?
?
PCTUSED
PCTUSED ? 參數用于決定一個數據塊(data block)是否可被用于插入新數據,她的依據是數據區(row data)與數據塊頭(overhead)的容量之和占數據塊全部容量的最大百分比。當一個數據塊中的可用空間比例小于? PCTFREE? 參數的規定時,Oracle就認為此數據塊無法被用于插入新數據,直到數據塊中的占用容量比例小于? PCTUSED? 參數的限定。 ? 在數據塊中的可用空間PCTFREE重新大于且占用容量比例大于 PCTUSED 參數的限定之前,Oracle只在更新數據塊內已有數據時才會使用此數據塊的可用空間,插入操作不使用該數據塊的可用空間 ? 。例如,當用戶用 ? CREATE TABLE ? 語句創建表時指定了以下參數:PCTUSED 40。
在例子中,當此表的某數據塊占用容量比例高于40%時,Oracle不會將此數據塊用于插入新數據行(假設此數據塊的可用空間曾經低于? PCTFREE ? 的限定)。 下圖說明了? PCTUSED ? 的作用。
?
?
在新分配的數據塊中(data block),可用于插入(insert)數據的空間等于數據塊總容量減去數據塊頭(block overhead)再減去預留可用空間( ? PCTFREE ? )。而更新(update)數據塊內已有數據可使用數據塊中的所有可用空間。因此,更新操作能夠使數據塊內的可用空間低于的? PCTFREE ? 限制,因為這些空間是專為更新操作而預留的。
在每個數據段(data segment)與索引段(index segment)中,選擇段的手動方式時,ORACLE管理著一個或多個可用塊列表(free list)--其中列出了所有屬于此段的數據擴展(extent),且可用空間比例大于? PCTFREE? 限定的數據塊。這些塊可以被插入(insert)操作使用。 ? 當用戶提交了 INSERT 語句后,Oracle從free list列表中選擇第一個有效的數據塊使用。如果此數據塊的可用空間不夠容納? INSERT 語句提交的數據,且此塊的占用容量已經超過 ? PCTUSED 的限定,Oracle就將其從可用塊列表中移出。一個段可以同時使用多個可用塊列表,以減少對一個表進行并發插入時產生的競爭。
當用戶提交了? DELETE 或? UPDATE 語句后,Oracle處理語句并檢查相關數據塊中的占用空間比例是否小于? PCTUSED 的規定。如果滿足,那么這個數據塊就被放入當前事務正在使用的可用塊列表(free list)的頭部,如果當前事務還需要寫入數據,此塊將被首先使用。當事務提交后,此數據塊中的可用空間還可被其他事務使用。
在段的手動管理模式下塊的空間管理可參見下圖
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
