Oracle Lob型別相關引數以及效能影響

realkid4發表於2011-09-27

 

Oracle Lob型別是Oracle資料庫提供的一種將非標準格式檔案或者資訊儲存在資料庫儲存系統的一種列型別。相對於傳統的關係型資料,Lob型別的資料覆蓋型別更加多樣,同樣也就面對更多的儲存、檢索和更新方面的效能問題。

 

目前,Oracle顯示支援的Lob型別子類包括四個,分別為CLOBBLOBNLOBBFILE。針對不同的資料型別,我們選擇不同的Lob子型別進行匹配。在四種型別中,前三種是真實將資料儲存在資料庫中,而BFILE的真實資料則是儲存在資料庫外。

 

本篇將針對Lob型別在儲存上使用的一些特殊屬性,進行簡單的介紹說明。同時推薦一些常用的Lob儲存最佳化手段。

 

1LobSegmentLogIndex

 

包括Lob型別列的資料表在段結構上存在一些特殊性。最直接的表現就是Lob資料段和Lob索引段的額外建立。

 

 

SQL> select * from v$version;

 

BANNER

----------------------------------------------------------------

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod

PL/SQL Release 10.2.0.1.0 - Production

CORE     10.2.0.1.0       Production

 

TNS for 32-bit Windows: Version 10.2.0.1.0 - Production

NLSRTL Version 10.2.0.1.0 – Production

 

 

當我們建立一個資料表T,其中包括lob型別列時。

 

 

SQL> create table t (id number, cl clob);

Table created

 

SQL> select segment_name, segment_type, tablespace_name from user_segments;

 

SEGMENT_NAME                   SEGMENT_TYPE       TABLESPACE_NAME

------------------------------ ------------------ ------------------------------

SYS_LOB0000056106C00002$$      LOBSEGMENT         USERS

T                              TABLE              USERS

SYS_IL0000056106C00002$$       LOBINDEX           USERS

 

 

9 rows selected

 

 

當資料表中有一個lob型別列時,Oracle會自動多建立出兩個列,一個是儲存lob資料的lob segment,另一個是對這個lob列生成的索引。注意,這個索引是由Oracle自動建立和管理,與lob列共生不能被單獨刪除。

 

此處存在一些經驗實踐專案,如果lob列對應的段和索引很大時,處於平衡IO的目的,可以考慮將lob列段和索引與資料表分開,單獨放置在其他表空間上。進而實現放置在不同資料磁碟的目的。這部分實驗可以參見筆者之前文章《Oracle Lob型別儲存淺析》(http://space.itpub.net/17203031/viewspace-708336)。

 

注意,這裡我們的Lob資料段和索引段是要放置在同一個表空間中的。這個與我們通常的經驗相左。Oracle 8i中,使用者是可以指定lob index的建立和管理的。但是從9i開始,這種控制權就被Oracle內部所回收,如果我們試圖使用8i時代的DDL語句進行指定,將lob資料和索引分離儲存,從前端上執行語句是不會有錯誤報出的。但是最終結果上沒有任何變化。相當於強制要求lob data segmentlob index segment存放在同一個表空間上。

 

 

2Lob資料表儲存引數

 

Lob列資料和一般資料存在很大的差異,所以在儲存方面也有很多獨特的特性存在。下面分別介紹一些與Lob儲存相關的重要引數型別和含義。

 

 

CREATE TABLE "SCOTT"."T"

   ( "ID" NUMBER,

       "CL" CLOB

   )

  TABLESPACE "USERS"

 LOB ("CL") STORE AS (

  TABLESPACE "USERS" ENABLE STORAGE IN ROW CHUNK 8192 PCTVERSION 10

  NOCACHE LOGGING

  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)) ;

 

 

上面是將資料表T的建立DDL語句抽取出的程式碼片段。其中標註紅色的部分,明顯是針對Lob型別列CL進行的獨特store引數特性。其中包括enable storeage in rowchunkpctversion/retentioncachelogging。這些引數的設定與Oracle Lob類物件儲存和效能息息相關。

 

ü        Chunk——lob物件儲存最小單元

 

通常情況下,普通資料儲存是以位元組byte為單位寫入到資料塊datablock中。而lob型別存在一些特殊。LobSegment作為Lob資料的主體,是以chunk作為最小的分配單元。一個chunk的大小是資料塊大小db_block_size的整數倍。最大為32K

 

一個chunk只能儲存一個lob物件的資料。如果出現填不滿的情況,空閒空間是被置空的。

 

 

SQL> select table_name, column_name, chunk from user_lobs;

 

TABLE_NAME COLUMN_NAM      CHUNK

---------- ---------- ----------

T          CL               8192

 

 

如果一個chunk8K的空間,對一個lob只有1K的大小,那麼Oracle為這個lob只會分配一個chunk,而且這個chunk是為了這個lob唯一獨佔的。剩餘的7K空間是剩下留空的。

 

同資料塊大小db_block_size確定之後不能修改有差別,chunk是資料lob段級別的引數。從上面的定義語句可以看出,即使在一個資料表中有多個lob列,也是可以分別制定不同的chunk大小的。所以說,chunk大小的選擇要針對lob的實際而“度身定製”!

 

一旦確定了chunk的大小,就不能在資料表中進行修改了。

 

那麼為lob選擇chunk大小是依據什麼準則呢?根據Oracle推薦,如果lob列儲存的資料是小於32K,那麼設定的chunk大小建議為lob60%比較合適。如果lob列儲存的資料是大於32K,那麼建議設定chunk的大小為經常進行update lob變化的大小。

 

ü        In-row storage and out-of-row storage

 

Oracle的確為了lob列值過大的情況,準備了專門lobsegment空間。但是實際上,Oracle是可以選擇lob資料的儲存方式的。Enable storage in row就意味著是否可以in row儲存功能,提供將lob資料儲存在資料段,和其他列儲存在一起的可能。

 

當我們開啟了in row storageOracle就會根據處理lob的大小選擇是否將其儲存在資料行中,而不是專門的lobsegment。當lob大小小於4000 bytesOracle會將它儲存在資料表段中,和同行的其他列儲存在一起。否則,才會儲存在專門的lobsegment中。如果lob資料是儲存在lobsegment裡,那麼資料行對應的位置上只會有一個很小的指向資訊,記錄對應的lobsegment位置。

 

 

SQL> select table_name, column_name, in_row from user_lobs;

 

TABLE_NAME COLUMN_NAM IN_ROW

---------- ---------- ------

T          CL         YES

 

 

lob store in row的情況而言,資料行的行遷移(row migration)和行連結(row chaining)是一直存在的。而且隨著資料塊大小與lob分配不匹配,這兩種現象會越來越嚴重。對lob store in row的資料來說,是不儲存在chunk單元上的。

 

如果lob資料儲存在其他的資料段上,那麼意味著我們每次讀取一行全部內容,都需要讀多個資料段的內容。這個顯然不是我們期望的結果。所以,在一般情況下,我們都會選擇enable storage in row來最佳化儲存。

 

考慮使用disable storage in row的可能性不是沒有,如果我們通常瀏覽資料是不包括lob型別或者很少包括lob型別,可以優先選擇使用lob型別。

 

 

ü        Cache/NoCache

 

普通資料表也是有cache引數選項,那麼引數意味著資料塊讀入到buffer cache中的管理策略:是一直駐留(Keep Pool)、常規駐留(Default Pool)還是用後清除(Recycle Pool)。

 

Lob資料而言,cachenocache的含義不同,意味著在使用訪問lob型別資料的時候,是否透過buffer cache進行讀寫。如果是nocache選項,則意味著Oracle在操作該Lob列的時候會繞開Buffer Cache,進行direct write/read操作。

 

 

SQL> select table_name, column_name, cache from user_lobs;

 

TABLE_NAME COLUMN_NAM CACHE

---------- ---------- ----------

T          CL         NO

 

 

設定這個引數的背景是lob型別資料在buffer cache中的管理問題。有時候由於體積等原因,buffer cache中的lob型別資料是會帶來很多的效能問題,特別是將其flushbuffer cache的過程。

 

通常情況下,我們還是希望設定為cache的,用來最佳化效能。直接對檔案的direct write/read通常不會有很好的效能。

 

注意:cache/nocache引數是針對在lobsegment中以chunk儲存的資料而言的,對能夠in-row storagelob而言,這個是不起作用的。因為in-row是以data block為基本操作單位。

 

 

ü        Lob型別資料的一致讀consisten read

 

多版本一致讀、當前讀是Oracle資料庫具有的獨特屬性,也是其最重要的特性之一。藉助undo表空間的前映象資料儲存,Oracle Server Process可以訪問到一些特定時間點(SCN)的資料,作為一致性讀取、免於髒資料。

 

但對於Lob型別而言,一致讀問題同樣存在。Oracle需要一種保留Lob資料映象的機制,儲存一系列old version。目前,Oracle提供了兩種維持機制來進行控制:基於時間的版本保留retention和基於空間的版本保留pctversion

 

 

SQL> select table_name, column_name, pctversion, retention from user_lobs;

 

TABLE_NAME COLUMN_NAM PCTVERSION  RETENTION

---------- ---------- ---------- ----------

T          CL                           900

 

 

Retention是表示採用基於時間版本保留策略。簡單的說,就是儘量保證保留一個時間段內的資料lob版本不會清除掉。在資料庫版本的相容性版本設定在9.2.0.0以上,並且undo_management引數值為true時,lob是預設直接使用retetion設定的。同時,使用的引數值與系統引數undo_retention相同。

 

 

SQL> show parameter comp

 

NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

compatible                           string      10.2.0.1.0

 

SQL> show parameter undo

 

NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

undo_management                      string      AUTO

undo_retention                       integer     900

undo_tablespace                      string      UNDOTBS1

 

 

引數pctversion只對於logsegment中使用chunk儲存的資料其效果。當pctversion=0的時候,表示舊版本資料是可以被其他事務產生的版本佔用。如果設定為100,就表示;舊版本資料永遠都不會被覆寫使用。

 

 

SQL> alter table t move lob(cl) store as t_segment (pctversion 10 disable storage in row);

 

Table altered

 

SQL> select table_name, column_name, pctversion, retention, in_row from user_lobs;

 

TABLE_NAME COLUMN_NAM PCTVERSION  RETENTION IN_ROW

---------- ---------- ---------- ---------- ------

T          CL                 10            NO

 

 

ü        Logging/NoLogging

 

設定logging屬性表示進行Lob資料變化的時候,要將變化的資訊記錄在redo log裡。而相反nologging表示資料不會記錄在redo log裡面。

 

注意幾個問題:當Lob資料設定為cache的時候,自動就是logging屬性。如果設定為nologging,只是lobsegment部分的資料變化不會寫redo log,不會影響到其他的in rowcolumn列的資料redo記錄工作。

 

 

3、結論

 

Lob型別是Oracle的一種較為特殊的資料型別。和其他資料相比具有儲存、使用上的特殊性。

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-708418/,如需轉載,請註明出處,否則將追究法律責任。

相關文章