分区表是我们面临海量数据环境中的一种方便常用的技术方案。根据业务系统的访问需求,将海量数据表分割为多个相对独立的数据段对象,可以有效的减少对海量数据全表的直接操作,提升整体性能。
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/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/17203031/viewspace-704826/