Oracle Lob型別儲存淺析

dawn009發表於2014-04-11

 

Oracle中,為資料表欄位columnPL/SQL語言,分別提供了多種資料型別,以應對實際開發中的多種型別。Lob型別是Oracle推出一種儲存大物件的資料型別。當我們考慮將資訊檔案(十進位制、二進位制)、影像甚至音訊資訊採用資料庫作為儲存載體時,就需要使用lob型別資料。

 

目前Oracle支援的Lob型別具體包括四個子型別(subtype),分別為CLOBBLOBNLOBBFILE。其中,CLOBBLOBNLOB都是將資料儲存在資料庫內部,而BFILE型別儲存的核心是檔案指標,真正的檔案是儲存在資料庫外。

 

與傳統的資料型別相比較,lob型別資料無論在管理上還是空間使用上,都有很多特殊之處。本篇主要介紹lob型別一些基本的儲存特性。

 

1、  環境準備和資料段segment特性

 

我們選擇在Oracle 10gR2下進行試驗。

 

 

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

 

 

使用create table命令,可以構建出一個實驗資料表T

 

 

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

Table created

 

 

對於一般的資料表而言,一個資料表只會對應一個儲存資料段data segment物件。這裡的特殊情況是分割槽表,通常一個分割槽就對應一個單獨的儲存物件。當資料表中包括lob型別的資料列時,也會有獨特的段物件建立。

 

 

SQL> select segment_name, segment_type, tablespace_name from user_segments;

 

SEGMENT_NAME                   SEGMENT_TY TABLESPACE_NAME

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

SYS_LOB0000056069C00002$$      LOBSEGMENT USERS

T                              TABLE      USERS

SYS_IL0000056069C00002$$       LOBINDEX   USERS

(篇幅原因,無關物件省略。。。。。。)

 

9 rows selected

 

 

我們發現,除了常規的資料段T之外,另外增加了兩個明顯是系統命名的段物件,型別分別為lobsegmentlobindex

 

Oracle lob型別資料表而言,一個帶lob列的資料表建立是要對應多個資料段建立的。除了傳統的資料表建立的資料段Table Data Segment之外,一個lob列都會生成兩個專門的段:lob段和lob索引段。

 

Lob段(LobSegment)對應的是存放在資料表lob列上的資料。在Oraclelob型別資料列,有兩種儲存位置結構。一個是in-row storage,也就是每一行的lob資料同其他列的資料以行的形式一起儲存在資料塊中。這種情況的lob列取值較小。而另一種為out-of-row storage,當lob物件較大,不能儲存在一個資料塊中時,可以將其放置在一個獨立lobsegment中進行儲存。而out-of-row storage時資料行中lob列上儲存的只是一個指向lobsegment對應位置的指標引用。

 

Lob索引段(LobIndex)是Oracle為每一個lob型別列強制生成的索引,主要作用是用於進行lob型別資料檢索加速的操作。Lobindexlob列共生,如果強制進行刪除操作,是會報錯的。

 

 

SQL> drop index SYS_IL0000056069C00002$$;

drop index SYS_IL0000056069C00002$$

 

ORA-22864: 無法 ALTER DROP LOB 索引

 

 

 

2lob型別資料表原始定義分析

 

使用dbms_metadata包,我們可以獲取到資料表的全部定義,包括各種預設引數和細節資訊。

 

 

CREATE TABLE "SCOTT"."T"

   ( "ID" NUMBER,

       "CL" CLOB

   ) 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 "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)) ;

 

  CREATE UNIQUE INDEX "SCOTT"."SYS_IL0000056069C00002$$" ON "SCOTT"."T" (

  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 "USERS"

  PARALLEL (DEGREE 0 INSTANCES 0) ;

 

 

可以看到我們抽取出的後設資料包括兩個組成部分,資料表建立部分和lob索引建立部分。在資料表建立部分,我們可以看到將lob作為一個獨立段物件進行儲存設定和引數設定。

 

lob索引建立部分,我們可以看到雖然是對應索引建立語句,但是從索引名稱上顯然是系統自動生成的物件名稱。

 

此外,還有很多是針對lob特殊的引數,如cacheenable storage in-row等,這些引數在資料表lob的行為和訪問效能上有巨大的影響。由於篇幅和內容所限,我們在本篇中不加以累述。

 

 

3lob段與lob索引儲存轉移

 

對於一個資料表涉及的多個段,很多時候我們需要將其進行移動處理。其中最常用的方法是使用move進行物件表空間的移動。

 

 

SQL> select segment_name, segment_type, tablespace_name from user_segments;

 

SEGMENT_NAME                   SEGMENT_TY TABLESPACE_NAME

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

SYS_LOB0000056099C00002$$      LOBSEGMENT USERS

T                              TABLE      USERS

SYS_IL0000056099C00002$$       LOBINDEX   USERS

 

9 rows selected

 

SQL> alter table t move tablespace system;

 

Table altered

 

SQL> select segment_name, segment_type, tablespace_name from user_segments;

 

SEGMENT_NAME                   SEGMENT_TY TABLESPACE_NAME

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

T                              TABLE      SYSTEM

SYS_LOB0000056099C00002$$      LOBSEGMENT USERS

SYS_IL0000056099C00002$$       LOBINDEX   USERS

 

9 rows selected

 

 

上面實驗可以明確看到,當使用一般的move命令時,只會將資料表T段進行移動到新表空間。Lob段和對應的lobindex段沒有變化。如果需要移動lob/lobindex,需要額外的單獨操作。

 

 

SQL> alter index SYS_IL0000056069C00002$$ rebuild tablespace users;

alter index SYS_IL0000056069C00002$$ rebuild tablespace users

 

ORA-02327: 無法以資料型別 LOB 的表示式建立索引

 

 

Lobindex是不能使用rebuild直接重構的。

 

 

SQL> select segment_name, segment_type, tablespace_name from user_segments;

 

SEGMENT_NAME                   SEGMENT_TY TABLESPACE_NAME

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

T_LOGSEGMENT                   LOBSEGMENT USERS

SYS_IL0000056069C00002$$       LOBINDEX   USERS

T                              TABLE      EXAMPLE

 

9 rows selected

 

SQL> alter table t move lob(cl) store as t_logsegment (tablespace example);

 

Table altered

 

SQL> select segment_name, segment_type, tablespace_name from user_segments;

 

SEGMENT_NAME                   SEGMENT_TY TABLESPACE_NAME

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

T                              TABLE      EXAMPLE

SYS_IL0000056069C00002$$       LOBINDEX   EXAMPLE

T_LOGSEGMENT                   LOBSEGMENT EXAMPLE

 

9 rows selected

 

 

使用alter table xxx move lob(xx) store as xxx (tablespace xxx);命令,我們可以進行lob列的儲存位置調節。

 

在建立資料表的時候,同樣可以使用lob(xxx)對應的資料表空間字句,執行儲存lob物件的空間資訊。

 

 

SQL> Create table DemoLob ( A number, B clob )

  2         LOB(b)

  3       STORE AS lobsegname (

  4         TABLESPACE users

  5         --STORAGE (lobsegment storage clause)

  6         INDEX lobindexname (

  7              TABLESPACE example

  8              --STORAGE ( lobindex storage clause )

  9         )

 10       )

 11        TABLESPACE system

 12       --STORAGE( tables storage clause )

 13       ;

 

Table created

 

SQL> select table_name, column_name, segment_name, tablespace_name, index_name from user_lobs;

 

TABLE_NAME COLUMN_NAM SEGMENT_NAME                   TABLESPACE_NAME                INDEX_NAME

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

T          CL         T_LOGSEGMENT                   EXAMPLE                        SYS_IL0000056069C00002$$

 

 

在實際物理設計部署過程中,經常有將大物件分割槽和儲存單獨部署表空間的情況。可以根據實際的情況,將一些很大的lob列連同索引儲存在單獨的表空間上。

 

但是注意,一般資料表而言,lob段和lobindex段是在一個表空間上。即使在SQL語法上存在支援,但是將lob段和lobindex分開儲存的語句通常被忽略掉。

 

 

 

SQL> alter table t move lob(cl) store as T_LOGSEGMENT (tablespace example index t_logindex (tablespace users));

 

Table altered

 

SQL> select table_name, column_name, segment_name, tablespace_name, index_name from user_lobs;

 

TABLE_NAME COLUMN_NAM SEGMENT_NAME                   TABLESPACE_NAME                INDEX_NAME

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

T          CL         T_LOGSEGMENT                   EXAMPLE                        SYS_IL0000056069C00002$$

 

SQL> select segment_name, segment_type, tablespace_name from user_segments;

 

SEGMENT_NAME                   SEGMENT_TY TABLESPACE_NAME

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

T                              TABLE      EXAMPLE

SYS_IL0000056069C00002$$       LOBINDEX   EXAMPLE

T_LOGSEGMENT                   LOBSEGMENT EXAMPLE

 

9 rows selected

 

 

4、結論

 

Lob型別是一種我們經常使用的複雜資料型別。處理和管理lob型別的方法和我們常規的手段存在很大差異,無論是開發還是運維過程中都要特別注意。

 

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

相關文章