近期來
FreeList的重要作用逐漸為Oracle DBA所認識
網上也出現一些相關的討論
本文以FreeList為線索對Oracle的存儲管理的原理進行較深入的探討
涉及Oracle段區塊管理的原理
FreeList算法等
而與FreeList密切相關的一個重用特性HWM
與sql性能密切相關
本文也作了原理分析介紹
在原理探討的基礎上
介紹了常用的存儲參數分析方法
並對所涉及的存儲優化
HWM的優化和Freelist競爭優化作了說明
縮略語
ASSMauto segement space management
HWMhigh water mark
DBAdata block address
OLTPonline transaction process
OPSoracle parallel server
簡介
Oracle的空間管理和存儲參數管理是Oracle管理及優化的重要部分FreeList作為Oracle底層存儲參數中的核心參數其行為方式對Oracle的存儲管理及性能優化有重大影響而現有的Oracle文檔對此方面的內容比較缺乏雖然Oracle i已出現了ASSM但是作為深入調優對FreeList認識仍是必要的
近期來FreeList的重要作用逐漸為Oracle DBA所認識網上也出現一些相關的討論本文以FreeList為線索對Oracle的存儲管理的原理進行較深入的探討涉及Oracle段區塊管理的原理FreeList算法等而與FreeList密切相關的一個重用特性HWM與sql性能密切相關本文也作了原理分析介紹在原理探討的基礎上介紹了常用的存儲參數分析方法並對所涉及的存儲優化HWM的優化和Freelist競爭優化作了說明
這些原理分析和性能優化都建立在探討的基礎上限於篇幅和本人經驗可能存在局限偏差或謬誤
為了准確文中部分結構和字段的說明直接用英文描述限於篇幅本文不對同樣很重要的block結構作更深入的討論對OPS性能有重要影響的free list group本文也未提及因此本文在單一free list group下討論對於block的深入討論free list group的介紹與優化以及PCTUSED和PCTFREE等重要參數的優化請參見參考文獻和資料
原理探討
FreeList作為一個Oracle存儲管理的核心參數其行為方式由Oralce內部控制我們一般不需要掌握和控制但是我們可能會遇到這些問題當插入一條記錄會插入到那個塊中?是使用新塊還是插入有數據的老塊?段是什麼時候擴展的如何擴展的?表中只有一條記錄但是作一次select時代價卻是上千個塊為什麼?如果我們從原理上清楚了Oracle的存儲管理方式對相關這些問題的解決及性能優化就清晰自然了
Oracle的邏輯儲存結構
Oralce的邏輯存儲結構按表空間段區塊進行管理塊是Oracle用來管理存儲空間的最基本單元Oracle數據庫在進行輸入輸出操作時都是以塊為單位進行邏輯讀寫操作的區由一系列連續的塊組成Oralce在進行空間分配回收和管理時是以區為基本單位的段由多個區組成這些區可以是連續的也可以是不連續的一般情況下一個對象擁有一個段表空間中容納段和區
在生成段的時候會同時分配初始區(initial extents) 初始區的第一個塊就格式化為segment header並被用來記錄free list描述信息extents信息HWM信息等
free list概念
free list是一種單向鏈表用於定位可以接收數據的塊在字典管理方式的表空間中Oracle使用free list來管理未分配的存儲塊Oracle記錄了有空閒空間的塊用於insert或Update空閒空間來源於兩種方式段中所有超過HWM的塊這些塊已經分配給段了但是還未被使用段中所有在HWM下的且鏈入了free list的塊可以被重用free list具有下列屬性
l flag指示free list 被使用()或未使用()
l free list 鏈的首塊的地址DBA(data block address)
l free list 鏈的尾塊的地址DBA
free list 的信息通常保留在segment header中這裡給出segment header block dump片段加以說明
nfl = nfb = typ = nxf =
SEG LST:: flg: UNUSED lhd: x ltl: x
SEG LST:: flg: USED lhd: xc ltl: xc
SEG LST:: flg: USED lhd: xc ltl: xc
SEG LST:: flg: UNUSED lhd: x ltl: x
Segment Header:
==> nfl: number of free lists/block
==> nfb: number of free list blocks + segment header
==> typ: block type
==> nxf: number of transaction free lists
Segment List:
==> flg: flag USED or UNUSED the free list
==> lhd: head of free list
==> ltl: tail of free list
在每一個塊中都有一個標記flg用來表明塊是否鏈入了 free list鏈中如果這個標志置上該塊中後向指針指向free list鏈中下一個塊的DBA如果當前塊是鏈的最末尾的塊該後向指針值為這裡給出位於free list上的block dump的片段
Block header dump: xc
Object id on Block? Y
seg/obj: xed csc: xc itc: flg: O typ: DATA
fsl: fnx: xc ver: x
==> Seg/obj Object ID in dictionary
==> csc SCN of last block cleanout
==> itc Number of ITL slots
==> flg O = On freelist = Not on freelist
==> typ = DATA = INDEX
==> fsl ITL TX freelist slot
==> fnx DBA of NEXT block on freelist
舉例來說如果有五個塊在free list中分別為ABCDE
就會形成segment header>A>B>C>D>E|
同時segment header>E
free list類別
在段中存在類free list 即Master Freelists (MFL) Process Freelists (PrFL) 和 Transaction Freelists
Master Free List(公用空閒空間池):
每一個段中有一個Master free list在段創建的時候自動生成對於每一個段來說都有這樣一個空閒空間池對每個進程都是公用的空閒空間就是位於master free list 的塊上由於Master free list是公用的因此當多個進程同時插入行到同一個段上master free list競爭使用程度就會增加
Process Free Lists
為了減少Master Free list的競爭問題 引入了另一種free list叫做Process free lists 根據sql命令 CREATE/ALTER 中的參數FREELISTS 創建 這樣多個free list 就可以分攤空閒空間的管理以提高OLTP應用作高度並發插入和更新事務時空間分配管理的性能通過指定CREATE TABLE / CLUSTER or INDEX的子句STORAGE的參數FREELISTS 來創建例如: CREATE TABLE flg ( ) STORAGE ( FREELISTS )缺省的FREELISTS為此時不會創建Process free lists當FREELISTS>=時創建Process free lists
進程在使用process free list是根據進程的Oracle PID (Process ID)來選擇的公式如下:
select list entry = (PID % NFL) +
NFL : FREELISTS定義的Process free list個數
Transaction Free Lists
當Oracle需要時動態創建一個Transaction Free List 是一種專門給某一個事務使用的free list 每個段至少有個transactions free lists 並且這個值在需要時會增長直到達到Segment Header塊的大小限制一個事務只有下面情況下會需要分配一個Tx Free Lists entry: 塊中釋放空間時(DELETE or UPDATE) 並且還不存在Tx Free Lists entry時
Free list行為
Freelist Link and Unlink 操作
Freelist 按後進先出隊列(LIFO) 方式管理也就是說最後被link到freelist的塊擁有最先unlink的機會當塊中空閒空間增加到大於PCTFREE時塊放入freelist中free list中的塊可用來作update 或insert 當塊中沒有足夠的空間用於insert操作時並且使用空間大於PCTUSED塊就會從free list中移出
在塊在DELETE or UPDATE 操作之後如果使用空間落到PCTUSED下塊再次link到free list中每次塊加入free list時都是link到鏈表的頭部
例如考慮段中有個塊編號由到其中有個塊在free list上並假設HWM是 (block實際使用DBA編號)
>>>>>|
現在作INSERT 操作需要 bytes空間假設塊上空間不足但塊上空間可用現在數據插入到塊 現在塊的剩余空間小於該表的PCTUSED因此塊 從free list鏈表中移出PCTFREE and PCTUSED參數的目的就是用來控制數據塊從free list的鏈表中移入/移出行為的現在free lists象這樣
>>>>|
然後在同一事務中作DELETE同一個段的數據使塊 和 落到PCTUSED下現在這些塊加入到free list鏈中free list鏈現在象這樣:
>>>>>>|
Transaction Free List 算法
掃描segment Header塊中所有的Tx free list檢查是否還沒有Tx free list entry分配給transaction 如何沒有將尋找未使用的entry或已經提交了事務的空的Tx free list如果上述搜索過程失敗 新的entry會在segment Header塊中Tx free lists區域中開辟如果沒有空間來生成 事務就必須等待entry的釋放
segment header中的最大free list個數:
Block Size Max # Freelists
K
K
K
k
事務T釋放出來的空閒塊(DELETE or UPDATE)的使用 :
l 立即被T所重用
l 當T commit後被其它需要空閒塊的事務重用過程舉例如下:
HMW概念
HIGH WATER MARK代表一個表使用的最大的(top limit)塊 中已經提到HIGH WATER MARK 記錄在segment header中並且在Oracle插入數據時一般增長個blocks(並非總是個塊具體參見中流程圖中HMW增長方式)
segment header block中與HWM相關信息說明如下:
EXTENT CONTROL:
Extent Header:: spare: space: #extents: #blocks:
last map x #maps: offset:
Highwater:: xd ext#: blk#: ext size:
#blocks in seg hdrs freelists:
#blocks below:
mapblk x offset:
Unlocked
==> spare: this field is no longer used (old inc# now always )
==> space: this field is no longer used (old ts# now always )
==> #extents: number of extents allocated to segment
==> #blocks: number of blocks allocated to segment
==> last map: address of last extent map block
if extent map is entirely in the segment header
==> #maps: number of extent map block
==> offset: offset to end of extent map
==> HWM dba: address of block at highwater mark
==> ext#: HWM extent number relative to segment
==> blk#: HWM block number within extent
==> ext size: HWM extent size (in blocks)
==> #blocks in seg hdrs freelists: number of blocks in seg hdrs free list
==> #blocks below: number of blocks below HWM
==> mapblk dba: dba of extent map block containing HWM extent
is if HWM is in the segment header
==> offset: offset within extent map block
is the ext# if HWM is in segment header
==> Locked by: if locked by a transaction the xid is displayed
HWM可以說是已經使用過的存儲空間和未使用過的存儲空間之間的分界線在表使用過程中HWM一直向一個方向移動插入記錄時HWM可能會向增加的方向移動但是刪除記錄時HWM並不會向相反的方向移動參見下圖顯示了某個數據段中HWM的位置情況
HIGH WATER MARK之所以重要是因為它對全表掃描性能的影響當實施一個全表掃描時Oracle會讀取所有HIGH WATER MARK下的塊即使它們是空塊當HIGH WATER MARK 下有很多unused block時實施全表掃描會增加額外的不必要的I/O它也會在全局共享區中填充很多很多空塊
分析方法
存儲參數基本上屬於oracle internal的東西因此oralce並沒有提供很好的手段來分析但是對於DBA來說還是可以通過block dump和DBMS_SPACE等手段來獲取部分信息
提取block和free list信息
創建dbms_space使用的存儲過程show_space
《
OracleFreelist和HWM原理及性能優化》本文是由
Oracle免費提供,內容來源於互聯網,本文歸原作者所有。