Exchange partition分割槽結構的“乾坤挪移”

realkid4發表於2011-08-14

 

分割槽表是我們面臨海量資料環境中的一種方便常用的技術方案。根據業務系統的訪問需求,將海量資料表分割為多個相對獨立的資料段物件,可以有效的減少對海量資料全表的直接操作,提升整體效能。

 

Oracle為分割槽表提供了很多分割槽操作,用來方便分割槽表資料的管理。其中,exchange partition是用於實現分割槽與資料表之間的交換操作。從效果上看,exchange partition就是將一個分割槽中填滿原先在一個資料表中的資料。但實際該操作的本質是什麼呢?本篇透過實驗來進行說明。

 

1、 實驗環境說明和資料準備

 

我們使用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

 

 

實驗資料選擇scott schema下的經典emp資料表。

 

 

SQL> create table t as select * from scott.emp;

 

Table created

 

 

 

2、 exchange partition實驗

 

exchange partition語句的使用語法為:

 

 

alter table xxx exchange partition A with table B;

 

 

含義是將資料表xxx的分割槽A替換為資料表B的內容。首先,我們使用t中的資料,構建出替換資料子表。

 

 

SQL> create table t_part1 as select * from t where sal<3000;

 

Table created

 

SQL> create table t_part2 as select * from t where sal>=3000 and sal<5000;

 

Table created

 

 

構建了兩個資料表t_part1和t_part2,儲存sal欄位小於3000和3000-5000的記錄值。

 

兩個資料表,我們分別檢視資料字典中的後設資料資訊。

 

 

SQL> select object_name, object_id, data_object_id, object_type from dba_objects where wner='SYS' and object_name in ('T_PART1','T_PART2');

 

OBJECT_NAM  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE

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

T_PART1         54439          54439 TABLE

T_PART2         54440          54440 TABLE

 

 

SQL> select segment_name, segment_type,HEADER_FILE, HEADER_BLOCK  from dba_segments where segment_name in ('T_PART1','T_PART2') and wner='SYS';

 

SEGMENT_NA SEGMENT_TYPE       HEADER_FILE HEADER_BLOCK

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

T_PART1    TABLE                        1        62377

T_PART2    TABLE                        1        62385

 

 

注意:資料表t_part1和t_part2是兩個普通資料表,對應的data_object_id分別為54439和54440,段頭對應的物理位置分別為(1,62377)和(1、62385)。data_object_id是Oracle內部物件的物理id編號,一定程度上反映了物件的物理位置資訊。

 

之後,我們構建分割槽表,使用sal進行範圍分割槽。

 

 

SQL> create table t_part

  2  (

  3    EMPNO    NUMBER(4),

  4    ENAME    VARCHAR2(10),

  5    JOB      VARCHAR2(9),

  6    MGR      NUMBER(4),

  7    HIREDATE DATE,

  8    SAL      NUMBER(7,2),

  9    COMM     NUMBER(7,2),

 10    DEPTNO   NUMBER(2)

 11  )

 12  partition by range(sal)

 13  (

 14    partition t_p1 values less than (3000),

 15    partition t_p2 values less than (5000)

 16  );

 

Table created

 

 

初始狀態下,t_part分割槽表中沒有資料。

 

 

SQL> select * from t_part;

 

EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO

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

 

 

我們檢查分割槽表的後設資料資訊,如下:

 

 

SQL> select object_name, object_id, data_object_id, object_type from dba_objects where wner='SYS' and object_name in ('T_PART','T_P1','T_P2');

 

OBJECT_NAM  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE

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

T_PART          54442          54442 TABLE PARTITION

T_PART          54443          54443 TABLE PARTITION

T_PART          54441                TABLE

 

 

 

SQL> select segment_name,PARTITION_NAME, segment_type,HEADER_FILE, HEADER_BLOCK  from dba_segments where segment_name in ('T_PART','T_P1','T_P2') and wner='SYS';

 

SEGMENT_NA PARTITION_NAME       SEGMENT_TYPE       HEADER_FILE HEADER_BLOCK

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

T_PART     T_P1                 TABLE PARTITION              1        62393

T_PART     T_P2                 TABLE PARTITION              1        62401

 

 

分割槽表是一種很特殊的段物件。通常情況下一個資料表對應一個段物件,只能分佈在一個表空間中。而分割槽表(分割槽索引)是包括多個段物件,一個分割槽對應一個段物件,理論上可以分佈在多個表空間中的。

 

我們透過資料字典檢查,發現了資料表T_PART,雖然佔據了物件dba_objects的一個條目,但是沒有對應的物理屬性編號data_object_id。而兩個分割槽被承認為獨立的分割槽,分配有象徵物理段物件的data_object_id,分別為54442和54443。從段頭資訊來看,兩個獨立的段T_P1和T_P2,分別佔據(1, 62393)和(1,62401)。

 

下面進行exchange partition實驗。

 

 

SQL> alter table t_part exchange partition t_p1 with table t_part1;

Table altered

 

SQL> alter table t_part exchange partition t_p2 with table t_part2;

Table altered

 

SQL> select count(*) from t_part;

 

  COUNT(*)

----------

        13

 

SQL> select count(*) from t_part partition(t_p1);

 

  COUNT(*)

----------

        11

 

SQL> select count(*) from t_part partition(t_p2);

 

  COUNT(*)

----------

         2

 

 

經過alter table exchange partition命令,我們成功的進行了分割槽資料表資訊的填入。下面,我們再次來觀察一下資料表t_part1和t_part2,分割槽表t_part的對應資訊和後設資料內容。

 

//原有資料表中內容為空;

SQL> select * from t_part1;

 

EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO

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

 

SQL> select * from t_part2;

 

EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO

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

 

 

 

原有兩個源資料表內容空空如也,似乎exchange partition操作不是簡單的資料集合複製。

 

//對比dba_objects情況;

SQL> select object_name, object_id, data_object_id, object_type from dba_objects where wner='SYS' and object_name in ('T_PART1','T_PART2');

 

OBJECT_NAM  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE

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

T_PART1         54439          54442 TABLE

T_PART2         54440          54443 TABLE

 

 

SQL> select object_name, object_id, data_object_id, object_type from dba_objects where wner='SYS' and object_name in ('T_PART','T_P1','T_P2');

 

OBJECT_NAM  OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE

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

T_PART          54442          54439 TABLE PARTITION

T_PART          54443          54440 TABLE PARTITION

T_PART          54441                TABLE

 

 

//對比dba_segments情況

SQL> select segment_name, segment_type,HEADER_FILE, HEADER_BLOCK  from dba_segments where segment_name in ('T_PART1','T_PART2') and wner='SYS';

 

SEGMENT_NAME         SEGMENT_TYPE    HEADER_FILE HEADER_BLOCK

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

T_PART1              TABLE                     1        62393

T_PART2              TABLE                     1        62401

 

SQL> select segment_name,PARTITION_NAME, segment_type,HEADER_FILE, HEADER_BLOCK  from dba_segments where segment_name in ('T_PART','T_P1','T_P2') and wner='SYS';

 

SEGMENT_NA PARTITION_NAME       SEGMENT_TYPE       HEADER_FILE HEADER_BLOCK

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

T_PART     T_P1                 TABLE PARTITION              1        62377

T_PART     T_P2                 TABLE PARTITION              1        62385

 

 

標註紅色的部分,均發生了變化。為了明顯的看出變化,我們使用下面資料表進行說明。

 

 

Before Exchange Operation

After Exchange Operation

obj_id

da_obj

file

block

obj_id

da_obj

file

block

t_part1

54439

54439

1

62377

54439

54442

1

62393

t_part2

54440

54440

1

62389

54440

54443

1

62401

t_part

54441

 

 

 

54441

 

 

 

t_p1

54442

54442

1

62393

54442

54439

1

62377

t_p2

54443

54443

1

62401

54443

54440

1

62389

 

3、 結論

 

經過上面資料表,我們已經很清晰的發現Oracle使用exchange partition的過程方法。在使用exchange partition的時候,Oracle並沒有將替換資料表的資料複製到分割槽中,而是進行了一系列段後設資料替換的操作。

 

Oracle將原有的資料表、分割槽物理段結構拆開,賦予一個新的邏輯名稱object_id,更新原有的資料資訊。這樣,就在沒有真正移動資料表資料的情況下,進行了資料的“乾坤挪移”。原來的資料表段,變成了分割槽段。而分割槽段變成了資料表段。

 

後設資料中的object_id,是統一對外邏輯編號。為了維持邏輯上物件還是原來的物件,要保證這個物件取值的一致性。

 

exchange partition操作的優點也就不難想象。如果是單純的複製,那麼消耗的空間是進行分割槽移植資料的兩倍,同時轉移效率會隨著分割槽中包括的資料量的大小而發生變化。exchange partition很類似truncate table,本質上是對段物件的DDL操作,保證只需要一份資料就可以加入到分割槽中。而且,當海量資料處理時,效率要遠遠高於複製操作。

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

相關文章