Oracle大物件資料儲存簡介

byfree發表於2009-10-20

1.Oracle大物件資料型別簡介
在Oracle的早期版本中,使用LONG和LONG RAW型別存放大物件資料。從8i版本開始,Oracle引入了LOB資料型別,並且Oracle建議開發人員儘量去使用LOB型別而不去使用LONG和LONG RAW。LOB型別和LONG、LONG RAW型別相比有幾個不同的地方。如:
        LOB(除了NCOLB)可以作為物件型別的一個屬性,但LONG型別不可以。
        LOB的最大值是4G,而LONG只有2G。
        LOB支援隨機訪問資料,但LONG只支援順序訪問。
LOB包括內部LOB和外部LOB,其中內部LOB(BLOB CLOB NCLOB)的資料存放到資料庫中,而外部LOB(BFILE)的資料存放在作業系統的檔案中。
具體說明如下:
BLOB:存放二進位制格式的資料,如:影像、音訊、視訊等。
CLOB:存放資料庫字符集格式的字元資料,如:大的文字資料。
NCLOB:存放Unicode字符集的字元資料。
BFILE:存放指向作業系統檔案的指標,並且該檔案即可以是文字檔案,也可以是二進位制檔案。當我們訪問該型別所表示的列時,只能讀取資料,不能修改。

以上CLOB、BLOB、NCLOB三種為內部LOB,從儲存和選項來看,它們都是一樣的。只不過CLOB和NCLOB支援文字資訊,而BLOB支援二進位制資訊。不論基型別是什麼,所指定的選項(CHUNKSIZE、PCTVERSION等)和要考慮的問題都是一樣的。為此以下只以其中一類做詳細說明。

2. 詳細說明LOB儲存屬性

SQL> create table test (id int primary key,txt clob);

表已建立。

SQL> set line 120
SQL> col SEGMENT_NAME format a40
SQL> select segment_name,segment_type from user_segments;

SEGMENT_NAME                             SEGMENT_TYPE                                                                  
---------------------------------------- ------------------                                                            
SYS_C005393                              INDEX                                                                         
SYS_IL0000052546C00002$$                 LOBINDEX                                                                      
SYS_LOB0000052546C00002$$                LOBSEGMENT                                                                    
TEST                                     TABLE                                                                         
這裡可以看到LOB欄位有兩個單獨的segment,型別分別為lobindex、lobsegment,lobindex用於存放索引資料,lobsegment用於存放lob資料。普通欄位只有在指明欄位為主鍵、外來鍵或指定索引等情況下,才會出現table segment和index segment兩部分。

SQL> set pagesize 999 long 2000
SQL> select dbms_metadata.get_ddl('TABLE','TEST') from dual;

DBMS_METADATA.GET_DDL('TABLE','TEST')                                                                                  
--------------------------------------------------------------------------------                                       
                                                                                                                       
  CREATE TABLE "TEST"."TEST"                                                                                           
   ( "ID" NUMBER(*,0),                                                                                                 
 "TXT" CLOB,                                                                                                           
  PRIMARY KEY ("ID")                                                                                                   
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255                                                                       
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645                                                
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)                                                     
  TABLESPACE "TEST"  ENABLE                                                                                            
   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING                                                  
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645                                                
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)                                                     
  TABLESPACE "TEST"                                                                                                    
 LOB ("TXT") STORE AS (                                                                                                
  TABLESPACE "TEST" 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))
以上用不同顏色標明瞭LOB欄位的四個主要屬性:
          TABLESPACE
          ENABLE STORAGE IN ROW
          CHUNK 8192
          PCTVERSION 10
          NOCACHE

TABLESPACE
這裡指定的TABLESPACE是儲存lobsegment和lobindex的表空間,這可能與表本身所在的表空間不同。也就是說,儲存LOB資料的表空間可能不同於儲存實際表資料的表空間。
為什麼考慮為LOB資料使用另外一個表空間(而不用表資料所在的表空間)呢?原因與管理和效能有關。從管理的角度看,LOB資料型別表示一種規模很大的資訊。如果表有數百萬行,而每行有一個很大的LOB,那麼LOB就會極為龐大。為LOB資料單獨使用一個表空間有利於備份和恢復以及空間管理,單從這一點考慮,將表與LOB資料分離就很有意義。例如,你可能希望LOB資料使用另外一個統一的區大小,而不是普通表資料所用的區大小。
另一個原因則出於I/O效能的考慮。預設情況下,LOB不在緩衝區快取中進行快取。因此,預設情況下,對於每個LOB訪問,不論是讀還是寫,都會帶來一個物理I/O(從磁碟直接讀,或者向磁碟直接寫)。那麼將這些物件分離到不同的磁碟上就很有意義。

ENABLE STORAGE IN ROW
此引數控制了LOB資料是否總與表分開儲存(儲存在lobsegment中)。如果設定了ENABLE STORAGE IN ROW,而不是DISABLE STORAGE IN ROW,小LOB(最多4,000位元組)就會像VARCHAR2一樣儲存在表本身中。只有當LOB超過了4,000位元組時,才會“移出”到lobsegment中。
LOB在4000byte以內,使用ENABLE STORAGE IN ROW比DISABLE STORAGE IN ROW快,總體系統消耗也較小。

引數調整例子:
ALTER TABLE tabname MODIFY LOB (lobname) (enable storage in row)
ALTER TABLE tabname MODIFY LOB (lobname) (disable storage in row)

CHUNK 8192
LOB欄位儲存塊的大小,CHUNK是邏輯上連續的一組資料庫塊(block),也是LOB的最小分配單元,通常資料庫的最小分配單元是資料庫塊,因此CHUNK大小必須是Oracle塊大小的整數倍。
當儲存LOB資料較大時,CHUNK大小設定大於8K有利於減小I/O的次數。例如,如果表中的LOB平均有7KB,而使用的CHUNK大小為32KB,對於每個LOB例項你都會“浪費”大約25KB的空間,另一方面,倘若使用8KB的CHUNK,就能使浪費減至最少。反之,如果有一個4MB的LOB,並使用8KB的CHUNK,你就至少需要512個CHUNK來儲存這個訊息。這也說明,至少需要512個lobindex條目指向這些CHUNK。這會影響獲取效能,因為與讀取更少但更大的CHUNK相比,要花更長的資料來讀取和管理許多小CHUNK。因此我們應該找到一個CHUNK大小與lobindex條目數比較平衡的“中間點”。

引數調整例子:
ALTER TABLE tabname MODIFY LOB (lobname) ( CHUNK n )

PCTVERSION 10
這用於控制LOB的讀一致性。lobsegment並不使用undo來記錄其修改,而是直接在lobsegment中維護資訊的版本。lobindex會像其他段一樣生成undo,但是lobsegment不會。修改一個LOB時,Oracle會分配一個新的CHUNK,並且仍保留原來的CHUNK。如果回滾了事務,對LOB索引所做的修改會回滾,索引將再次指向原來的CHUNK。因此,undo維護會在LOB段本身中執行。修改資料時,原來的資料庫保持不動,此外會建立新資料。
PCTVERSION控制著用於實現LOB資料版本化的已分配LOB空間的百分比(這些資料庫塊由某個時間點的LOB所用,並處在lobsegment的HWM以下)。對於許多使用情況來說,預設設定12%就足夠了,因為在很多情況下,你只是要INSERT和獲取LOB(通常不會執行LOB的更新;LOB往往會插入一次,而獲取多次)。因此,不必為LOB版本化預留太多的空間(甚至可以沒有)。
不過,如果應用確實經常修改LOB,倘若你頻繁地讀LOB,與此同時另外某個會話正在修改這些LOB,12%可能就太小,需適當增大該引數。

引數調整例子:
ALTER TABLE tabname MODIFY LOB (lobname) ( PCTVERSION n );

NOCACHE
這個子句控制了lobsegment資料是否儲存在緩衝區快取中。預設的NOCACHE指示,每個訪問都是從磁碟直接讀,類似地,每個寫/修改都是對LOB的一個直接寫。CACHE READS允許快取從磁碟讀的LOB資料,但是LOB資料的寫操作必須直接寫至磁碟。CACHE則允許讀和寫時都能快取LOB資料。
如果是中小規模的LOB(例如,使用LOB來儲存只有幾KB的描述性欄位),快取就很有意義。如果不快取,當使用者更新描述欄位時,還必須等待I/O將資料寫到磁碟(將執行一個CHUNK大小的I/O,而且使用者要等待這個I/O完成)。如果你在執行多個LOB的載入,那麼載入每一行時都必須等待前一個I/O完成。所以啟用執行LOB快取很合理。
為此需根據LOB欄位的大小與修改頻繁度來決定CACHE引數的設定。

引數調整例子:
ALTER TABLE tabname MODIFY LOB (lobname) ( CACHE );
ALTER TABLE tabname MODIFY LOB (lobname) ( CACHE READS);
ALTER TABLE tabname MODIFY LOB (lobname) ( NOCACHE );

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

相關文章