1. 程式人生 > >Oracle資料塊實現原理深入解讀

Oracle資料塊實現原理深入解讀

Oracle對資料庫資料檔案(datafile)中的儲存空間進行管理的單位是資料塊(data block),本文將詳細介紹。


Oracle對資料庫資料檔案(datafile)中的儲存空間進行管理的單位是資料塊(data block)。資料塊是資料庫中最小的(邏輯)資料單位。與資料塊對應的,所有資料在作業系統級的最小物理儲存單位是位元組(byte)。每種作業系統都有一個被稱為塊容量(block size)的引數。Oracle每次獲取資料時,總是訪問整數個(Oracle)資料塊,而不是按照作業系統塊的容量訪問資料。

資料庫中標準的資料塊(data block)容量是由初始化引數 DB_BLOCK_SIZE指定的。除此之外,使用者還可以指定五個非標準的資料塊容量(nonstandardblock size)。資料塊容量應該設為作業系統塊容量的整數(同時小於資料塊容量的最大限制),以便減少不必要的I/O操作。Oracle資料塊是Oracle可以使用和分配的最小儲存單位。

資料塊結構

在Oracle中,不論資料塊中儲存的是表(table)、索引(index)或簇表(clustered data),其內部結構都是類似的。塊結構圖如下所示:

本圖顯示了資料塊的各個組成部分,包括:資料塊頭(包括標準內容和可變內容)(common and variable header),表目錄區(table directory),行目錄區(row directory),可用空間區(free space),行資料區(row data)。圖中兩個箭頭表示一個數據塊中的可用空間區的容量是可變的。

資料塊頭(包括標準內容和可變內容)

資料塊頭(header)中包含了此資料塊的概要資訊,例如塊地址(block address)及此資料塊所屬的段(segment)的型別(例如,表或索引)。

表目錄區

如果一個數據表在此資料塊中儲存了資料行,那麼資料表的資訊將被記錄在資料塊的表目錄區(table directory)中。

行目錄區

此區域包含資料塊中儲存的資料行的資訊(每個資料行片斷(row piece) 在行資料區(row data area)中的地址)。[一個數據塊中可能儲存一個完整的資料行,也可能只儲存資料行的一部分 ,所以文中使用row piece]

當一個數據塊(data block)的行目錄區(row directory)空間被使用後,即使資料行被刪除(delete),行目錄區空間也不會被回收。舉例來說,當一個曾經包含50條記錄的資料塊被清空後,其塊頭(header)的行目錄區仍然佔用100位元組(byte)的空間

管理開銷

資料塊頭(data block header),表目錄區(table directory),行目錄區(rowdirectory)被統稱為管理開銷(overhead)。其中 有些開銷的容量是固定的;而有些開銷的總容量是可變的。資料塊中固定及可變管理開銷的容量平均在84到107位元組(byte)之間。

行資料

資料塊(data block)中行資料區(row data)包含了表或索引的實際資料。一個數據行可以跨多個數據塊。

可用空間區

在插入新資料行,或在更新資料行需要更多空間時(例如,原來某行最後一個欄位為空(trailing null),現在要更新為非空值),將 使用可用空間區(free space)中的空間。如果一個數據塊(data block)屬於表或簇表的資料段(data segment),或屬於索引的索引段(index segment),那麼在其可用空間區中還可能會儲存事務條目(transaction entry)。如果一個數據塊中的資料行(row)正在由INSERT,UPDATE,DELETE,及 SELECT...FOR UPDATE 語句訪問,此資料塊中就需要儲存事務條目。事務條目所需的儲存空間依據作業系統而定。在常見的作業系統中事務條目大約需要佔用23位元組(byte)。

可用空間管理

可用空間可以被手動或自動管理

資料庫中,每個段(segment)的可用空間可以被自動管理。段內的可用/已用空間以點陣圖(bitmap)形式記錄,這與可用塊以列表方式的管理不同。段空間自動管理(Automatic segment-space management)具備以下優勢:

● 易於使用● 空間利用效率更高,尤其針對每行資料容量差異大的表(或其他物件)● 能夠更好地針對當前資料的情況實時調整● Better multi-instance behavior. in terms of performance/space utilization

使用者可以在建立一個本地管理的表空間(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只在 滿足上述條件時才對資料塊中的可用空間進行合併,這樣做是為了避免過於頻繁的空間合併工作影響資料庫效能。

行連結(Row Chaining)及行遷移(Row Migrating)

有兩種情況會導致表中某行資料過大,一個數據塊(data block)無法容納。第一種情況,當一行資料被插入時一個數據塊就無法容納。在這種情況下Oracle將這行資料儲存在段內的一個數據塊鏈(chain)中。在插入資料量大的行時常會發生行連結(row chaining),例如一個包含資料型別為 LONG 或LONG RAW 列的資料行。此時行連結不可避免。

第二種情況,原本儲存在一個數據塊(data block)內的資料行,因為更新操作導致長度增長,而所在資料塊的可用空間也不能容納增長後的資料行。在這種情況下,Oracle將此行資料遷移(migrate)到新的資料塊中。Oracle在被遷移資料行原來所在位置儲存一個指向新資料塊的指標。被遷移資料行的rowid 保持不變。

當資料行發生連結(chain)或遷移(migrate)時,對其訪問將會造成 I/O 效能降低,因為Oracle為獲取這些資料行的資料時,必須訪問更多的資料塊(data block)。

PCTFREE,PCTUSED,及行連結(Row Chaining)

在手動管理的表空間(manually managed tablespaces)中,使用者可以使用PCTFREE 和 PCTUSED 這兩個儲存管理引數來控制對某段(segment)進行插入和更新操作時,如何利用屬於此段的資料塊(data block)中的可用空間。使用者也可以在建立或修改索引時為其設定 PCTFREE 引數(索引儲存在索引段(index segment)中)

PCTFREE 引數

PCTFREE 引數用來設定一個數據塊(data block)中至少需要保留(reserve)多少可用空間(百分比值),為資料塊中已有資料更新時可能發生的資料量增長做準備。例如,當用戶用 CREATE TABLE 語句建立表時指定了以下引數:

PCTFREE 20

這個引數設定了此表對應的資料段(data segment)中的每個資料塊(datablock)至少保留20%的可用空間,以備塊中已有資料更新時使用。只要資料塊中行資料區與資料塊頭的容量之和不超過資料塊總容量的80%,使用者就可以向其中插入新資料,資料行被放入行資料區(row data area),相關資訊被寫入資料塊頭(overhead area)

下圖說明了PCTFREE 的作用:

PCTUSED 引數

PCTUSED 引數用於決定一個數據塊(data block)是否可被用於插入新資料,她的依據是資料區(row data)與資料塊頭(overhead)的容量之和佔資料塊全部容量的最大百分比。當一個數據塊中的可用空間比例小於PCTFREE 引數的規定時,Oracle就認為此資料塊無法被用於插入新資料,直到資料塊中的佔用容量比例小於 PCTUSED 引數的限定。在佔用容量比例大於 PCTUSED 引數的限定之前,Oracle只在更新資料塊內已有資料時才會使用此資料塊的可用空間。例如,當用戶用 CREATE TABLE 語句建立表時指定了以下引數:

PCTUSED 40

在例子中,當此表的某資料塊佔用容量比例高於40%時,Oracle不會將此資料塊用於插入新資料行(假設此資料塊的可用空間曾經低於 PCTFREE 的限定)

PCTUSED 的作用

PCTFREE 和 PCTUSED 如何協同發揮作用

PCTFREE 和 PCTUSED 共同作用可以優化資料塊(data block)的空間使用。

使用 PCTFREE 和 PCTUSED 引數管理資料塊的可用空間

上圖說明了 PCTFREE 和 PCTUSED 如何共同作用以管理資料塊(data block)可用空間的使用。

在第一步中,資料塊佔用空間比例小於80%時才能插入新資料,因為PCTFREE 引數限定必須保留20%的可用空間用於塊內已有資料的更新。在第二步中,對資料塊中已有資料的更新操作可以使用資料塊中的保留空間。只有當資料塊內的佔用空間比例低於40%時才能向其中插入新資料。在第三步中,當資料塊內的佔用空間比例低於40%時,此資料塊再次可以被用於插入新資料。在第四步中,資料塊佔用空間比例小於80%時才能插入新資料,因為PCTFREE 引數限定必須保留20%的可用空間用於塊內已有資料的更新。此過程如此往復迴圈。

在新分配的資料塊中(data block),可用於插入(insert)資料的空間等於資料塊總容量減去資料塊頭(block overhead)再減去預留可用空間(PCTFREE)。而更新(update)資料塊內已有資料可使用資料塊中的所有可用空間。因此,更新操作能夠使資料塊內的可用空間低於的 PCTFREE 限制,因為這些空間是專為更新操作而預留的。

在每個資料段(data segment)與索引段(index segment)中,Oracle管理著一個或多個可用塊列表(free list)--其中列出了所有屬於此段的資料擴充套件(extent),且可用空間比例大於 PCTFREE 限定的資料塊。這些塊可以被插入(insert)操作使用。當用戶提交了 INSERT 語句後,Oracle從可用塊列表中選擇第一個有效的資料塊使用。如果此資料塊的可用空間不夠容納 INSERT語句提交的資料,且此塊的佔用容量已經超過PCTUSED 的限定,Oracle就將其從可用塊列表中移出。一個段可以同時使用多個可用塊列表,以減少對一個表進行併發插入(concurrent insert)時產生的競爭。

當用戶提交了 DELETE 或 UPDATE 語句後,Oracle處理語句並檢查相關資料塊中的佔用空間比例是否小於 PCTUSED 的規定。如果滿足,那麼這個資料塊就被放入當前事務(transaction)正在使用的可用塊列表(free list)的頭部,如果當前事務還需要寫入資料,此塊將被首先使用。當事務提交後,此資料塊中的可用空間還可被其他事務使用。