Oracle效能調優之FreeList和HWM
在本文中,我們將以FreeList為線索對Oracle的儲存管理的原理進行較深入的講解,涉及Oracle段區塊管理的原理,FreeList演算法等。而與FreeList密切相關的一個重用特性HWM,與sql效能密切相關,本文也作了原理分析介紹。在原理探討的基礎上,介紹了常用的儲存引數分析方法,並對所涉及的儲存優化、HWM的優化和Freelist競爭優化作了詳細的說明。
縮略語如下:
ASSM:auto segement space management
HWM:high water mark
DBA:data block address
OLTP:online transaction process
OPS:oracle parallel server
1.前言
Oracle的空間管理和儲存引數管理是Oracle管理及優化的重要部分。FreeList作為Oracle底層儲存引數中的核心引數,其行為方式對Oracle的儲存管理及效能優化有重大影響,而現有的Oracle文件對此方面的內容比較缺乏。雖然Oracle 9i已出現了ASSM,但是作為深入調優對FreeList認識仍是必要的。
這些原理分析和效能優化都建立在探討的基礎上,限於篇幅和本人經驗可能存在侷限、偏差或謬誤。
為了準確文中部分結構和欄位的說明直接用英文描述。
限於篇幅本文不對同樣很重要的block結構作更深入的討論,對OPS效能有重要影響的free list group本文也未提及,因此本文在單一free list group下討論。對於block的深入討論、free list group的介紹與優化以及PCTUSED和PCTFREE等重要引數的優化請參見參考文獻和資料。
2.原理探討
FreeList作為一個Oracle儲存管理的核心引數。其行為方式由Oralce內部控制,我們一般不需要掌握和控制。但是我們可能會遇到這些問題,當插入一條記錄,會插入到那個塊中?是使用新塊,還是插入有資料的老塊?段是什麼時候擴充套件的,如何擴充套件的?表中只有一條記錄,但是作一次select時代價卻是上千個塊,為什麼?如果我們從原理上清楚了Oracle的儲存管理方式,對相關這些問題的解決及效能優化就清晰自然了。
2.1 Oracle的邏輯儲存結構
Oralce的邏輯儲存結構按表空間,段,區,塊進行管理。塊是Oracle用來管理儲存空間的最基本單元,Oracle資料庫在進行輸入輸出操作時,都是以塊為單位進行邏輯讀寫操作的。區由一系列連續的塊組成,Oralce在進行空間分配、回收和管理時是以區為基本單位的。段由多個區組成,這些區可以是連續的也可以是不連續的,一般情況下一個物件擁有一個段。表空間中容納段和區。
在生成段的時候,會同時分配初始區(initial extents), 初始區的第一個塊就格式化為segment header,並被用來記錄free list描述資訊、extents資訊,HWM資訊等。
2.2 free list概念
free list是一種單向連結串列用於定位可以接收資料的塊,在字典管理方式的表空間中,Oracle使用free list來管理未分配的儲存塊。Oracle記錄了有空閒空間的塊用於insert或Update。空閒空間來源於兩種方式:1.段中所有超過HWM的塊,這些塊已經分配給段了,但是還未被使用。2.段中所有在HWM下的且鏈入了free list的塊,可以被重用。free list具有下列屬性
flag指示free list 被使用(1)或未使用(0)
free list 鏈的首塊的地址DBA(data block address)
free list 鏈的尾塊的地址DBA
free list 的資訊通常保留在segment header中,這裡給出segment header block dump片段加以說明:
nfl = 3, nfb = 1 typ = 1 nxf = 0
SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
SEG LST:: flg: USED lhd: 0x03c00233 ltl: 0x03c00233
SEG LST:: flg: USED lhd: 0x03c00234 ltl: 0x03c00234
SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
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。如果當前塊是鏈的最末尾的塊,該後向指標值為0。
這裡給出位於free list上的block dump的片段
Block header dump: 0x03c00235
Object id on Block? Y
seg/obj: 0xe2d8 csc: 0x00.6264c61 itc: 1 flg: O typ: 1 - DATA
fsl: 1 fnx: 0x3c00234 ver: 0x01
==> 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 1 = DATA 2 = INDEX
==> fsl ITL TX freelist slot
==> fnx DBA of NEXT block on freelist
舉例來說如果有五個塊在free list中,分別為A,B,C,D,E
就會形成segment header->A->B->C->D->E--|
同時segment header->E
2.3 free list類別
在段中存在3類free list, 即Master Freelists (MFL), Process Freelists (PrFL), 和 Transaction Freelists.
2.3.1 Master Free List(公用空閒空間池):
每一個段中有一個Master free list,在段建立的時候自動生成。對於每一個段來說都有這樣一個空閒空間池,對每個程式都是公用的,空閒空間就是位於master free list 的塊上。由於Master free list是公用的,因此當多個程式同時插入行到同一個段上,master free list競爭使用程度就會增加。
2.3.2 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 10 ...)。預設的FREELISTS為1,此時不會建立Process free lists。當FREELISTS>=2時,建立Process free lists。
程式在使用process free list是根據程式的Oracle PID (Process ID)來選擇的,公式如下:
select list entry = (PID % NFL) + 1
NFL : FREELISTS定義的Process free list個數
2.3.3 Transaction Free Lists
當Oracle需要時動態建立。一個Transaction Free List 是一種專門給某一個事務使用的free list. 每個段至少有16個transactions free lists, 並且這個值在需要時會增長,直到達到Segment Header塊的大小限制。一個事務只有下面情況下會需要分配一個Tx Free Lists entry: 塊中釋放空間時(DELETE or UPDATE) 並且還不存在Tx Free Lists entry時。
2.4 Free list行為
2.4.1 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到連結串列的頭部。
例如:考慮段中有120個塊編號由1到120。其中有6個塊在free list上並假設HWM是 80。(block實際使用DBA編號)
10->24->45->46->65->80-|
現在作INSERT 操作,需要400 bytes空間。假設塊10上空間不足,但塊24上空間可用。現在資料插入到塊 24 ,現在塊24的剩餘空間小於該表的PCTUSED。因此塊 24 從free list連結串列中移出。PCTFREE and PCTUSED引數的目的就是用來控制資料塊從free list的連結串列中移入/移出行為的。現在free lists象這樣:
10->45->46->65->80-|
然後在同一事務中作DELETE同一個段的資料,使塊 54 和 67落到PCTUSED下。現在這些塊加入到free list鏈中。free list鏈現在象這樣:
67->54->10->45->46->65->80-|
2.4.2 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
----------- -----------------
2K 24
4K 50
8K 101
16k 204
事務T1釋放出來的空閒塊(DELETE or UPDATE)的使用 :
l 立即被T1所重用
l 當T1 commit後被其它需要空閒塊的事務重用,過程舉例如下:
2.5 HMW概念
HIGH WATER MARK代表一個表使用的最大的(top limit)塊 。2.1中已經提到HIGH WATER MARK 記錄在segment header中,並且在Oracle插入資料時一般增長5個blocks(並非總是5個塊,具體參見2.4.2中流程圖中HMW增長方式)。
segment header block中與HWM相關資訊說明如下:
EXTENT CONTROL:
Extent Header:: spare1: 0 space2: 0 #extents: 13 #blocks: 1429
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x020004d0 ext#: 12 blk#: 275 ext size: 475
#blocks in seg. hdr’s freelists: 5
#blocks below: 1229
mapblk 0x00000000 offset: 12
Unlocked
==> spare1: this field is no longer used (old inc#, now always 0)
==> space2: this field is no longer used (old ts#, now always 0)
==> #extents: number of extents allocated to segment
==> #blocks: number of blocks allocated to segment
==> last map: address of last extent map block
0 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. hdr’s freelists: number of blocks in seg. hdr’s free list
==> #blocks below: number of blocks below HWM
==> mapblk dba: dba of extent map block containing HWM extent
is 0 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並不會向相反的方向移動。
HIGH WATER MARK之所以重要是因為它對全表掃描效能的影響。當實施一個全表掃描時,Oracle會讀取所有HIGH WATER MARK下的塊即使它們是空塊。當HIGH WATER MARK 下有很多unused block時實施全表掃描會增加額外的不必要的I/O。它也會在全域性共享區中填充很多很多空塊。
3.分析方法
儲存引數基本上屬於oracle internal的東西,因此oralce並沒有提供很好的手段來分析。但是對於DBA來說,還是可以通過block dump和DBMS_SPACE等手段來獲取部分資訊。
3.1 提取block和free list資訊
建立dbms_space使用的儲存過程show_space
SQL>
create or replace procedure show_space
( p_segname in varchar2,
p_owner in varchar2 default user,
p_type in varchar2 default 'TABLE',
p_partition in varchar2 default NULL )
as
l_free_blks number;
l_total_blocks number;
l_total_bytes number;
l_unused_blocks number;
l_unused_bytes number;
l_LastUsedExtFileId number;
l_LastUsedExtBlockId number;
l_last_used_block number;
procedure p( p_label in varchar2, p_num in number )
is
begin
dbms_output.put_line( rpad(p_label,40,'.') || p_num );
end;
begin
dbms_space.free_blocks
( segment_owner => p_owner,
segment_name => p_segname,
segment_type => p_type,
partition_name => p_partition,
freelist_group_id => 0,
free_blks => l_free_blks );
dbms_space.unused_space
( segment_owner => p_owner,
segment_name => p_segname,
segment_type => p_type,
partition_name => p_partition,
total_blocks => l_total_blocks,
total_bytes => l_total_bytes,
unused_blocks => l_unused_blocks,
unused_bytes => l_unused_bytes,
last_used_extent_file_id => l_LastUsedExtFileId,
last_used_extent_block_id => l_LastUsedExtBlockId,
last_used_block => l_last_used_block );
p( 'Free Blocks', l_free_blks );
p( 'Total Blocks', l_total_blocks );
p( 'Total Bytes', l_total_bytes );
p( 'Unused Blocks', l_unused_blocks );
p( 'Unused Bytes', l_unused_bytes );
p( 'Last Used Ext FileId', l_LastUsedExtFileId );
p( 'Last Used Ext BlockId', l_LastUsedExtBlockId );
p( 'Last Used Block', l_last_used_block );
end;
過程已建立。
SQL> create table t1(a char(1000)) storage( freelists 3);
表已建立。
SQL> set serveroutput on;
SQL> exec show_space('T1');
Free Blocks.............................0 <==Number of blocks on freelist
Total Blocks............................5 <==Total data blocks in segment
Total Bytes.............................20480 <==Total bytes in segment
Unused Blocks...........................4 <==Total unused blocks in segment
Unused Bytes............................16384 <==Total unused bytes in segment
Last Used Ext FileId....................15 <==File id of last used extent
Last Used Ext BlockId...................562 <==Block id of last used extent
Last Used Block.........................1 <==Last used block in extent
PL/SQL 過程已成功完成。
有關show_space的進一步使用技巧可參考文獻5。以下利用上面得到的資料對segment header block進行dump。
SQL>alter system dump datafile 15 block 562;
在udump/ora10792.trc中
*** 2004-09-08 15:29:57.343
Start dump data blocks tsn: 27 file#: 15 minblk 562 maxblk 562
buffer tsn: 27 rdba: 0x03c00232 (15/562)
scn: 0x0000.064560e4 seq: 0x02 flg: 0x00 tail: 0x60e41002
frmt: 0x02 chkval: 0x0000 type: 0x10=DATA SEGMENT HEADER - UNLIMITED
Extent Control Header
-----------------------------------------------------------------
Extent Header:: spare1: 0 space2: 0 #extents: 1 #blocks: 4
last map 0x00000000 #maps: 0 offset: 2080
Highwater:: 0x03c00233 ext#: 0 blk#: 0 ext size: 4
#blocks in seg. hdr's freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
Unlocked
Map Header:: next 0x00000000 #extents: 1 obj#: 60033 flag: 0x40000000
Extent Map
-----------------------------------------------------------------
0x03c00233 length: 4
nfl = 3, nfb = 1 typ = 1 nxf = 0
SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25148509/viewspace-1047294/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle效能調優 之FreeList和HWMOracle
- Oracle Freelist和HWM的效能優化Oracle優化
- 轉:Oracle Freelist和HWM的效能優化Oracle優化
- Oracle Freelist和HWM原理探討及相關效能優化Oracle優化
- Oracle Freelist和HWM原理探討及相關效能優化(轉)Oracle優化
- Oracle Freelist和HWM原理及效能最佳化(轉)Oracle
- ORACLE FREELIST HWM(轉)Oracle
- ORACLE FREELIST HWM(3)Oracle
- ORACLE FREELIST HWM(2)Oracle
- ORACLE FREELIST HWM(1)Oracle
- Oracle Freelist和HWM原理探討及相關效能最佳化Oracle
- Oracle Freelist和HWM原理探討及相關效能最佳化(1)Oracle
- Oracle Freelist和HWM原理探討及相關效能最佳化(2)Oracle
- Oracle Freelist和HWM原理探討及相關效能最佳化(3)Oracle
- Oracle高水位線(HWM)及效能優化Oracle優化
- Oracle案例10——HWM(高水位線)效能優化Oracle優化
- Oracle 之HWMOracle
- oracle效能調優Oracle
- Oracle 效能調優 概述Oracle
- oracle筆記整理13——效能調優之SQL優化Oracle筆記SQL優化
- 效能調優學習之硬體調優
- Oracle效能調優原則Oracle
- oracle效能調優:管理oracle日誌之調整線上日誌檔案Oracle
- oracle筆記整理14——效能調優之oracle執行計劃Oracle筆記
- oracle筆記整理12——效能調優之hint標籤Oracle筆記
- ORACLE DW效能調優研究方向Oracle
- 效能調優命令之jstackJS
- Oracle效能調整之--DML語句效能調整Oracle
- Linux系統效能調優之效能分析Linux
- 部落格連結—Oracle效能調優Oracle
- oracle效能優化-共享池調整Oracle優化
- 針對oracle效能的io調優Oracle
- Linux效能調優命令之freeLinux
- Android效能調優工具之 TraceViewAndroidView
- ORACLE之常用FAQ:效能調整Oracle
- oracle筆記整理11——效能調優之oracle等待事件與表關聯Oracle筆記事件
- Oracle HWMOracle
- oracle效能優化之--hintsOracle優化