交换分区Exchange partition:提供了一种方式,让你在表与表或分区与分区之间迁移数据,注意不是将表转换成分区或非分区的形式,而仅只是迁移表中数据(互相迁移),由于其号称是采用了更改数据字典的方式,因此效率最高(几乎不涉及io操作)。Exchange partition适用于所有分区格式,你可以将数据从分区表迁移到非分区表,也可以从非分区表迁移至分区表。
语法:alter table tbname1 exchange partition/subpartition ptname with table tbname2;
含义: 将表tbname1中的ptname分区与表tbname2进行交换
实质:只是交换了名称,类似于指针的指向的内容发生了变化。
注意:在将未分区表的数据迁移到分区表中时,可能出现ora-14099的错误,虽然可以用without validation去解决,但是此时进入分区表的数据可能不符合分区规则。所以without validation一定要慎用。
l. 涉及交换的两表之间表结构必须一致,除非附加with validation子句;
2. 如果是从非分区表向分区表做交换,非分区表中的数据必须符合分区表中指定分区的规则,除非附加without validation子句;
3. 如果从分区表向分区表做交换,被交换的分区的数据必须符合分区规则,除非附加without validation子句;
4. Global索引或涉及到数据改动了的global索引分区会被置为unusable,除非附加update indexes子句。
提示:一旦附加了without validation子句,则表示不再验证数据有效性,因此指定该子句时务必慎重。
应用:可以使用在分区表导出时,建立临时表与分区进行交换(这样临时表内容指向原来的分区,并且是自包含的),然后进行表空间的迁移。
--创建分区表
SCOTT@ORA11GR2>create table test_par
2 (
3 nid number(10) constraint pk_test_p primary key,
4 idcard varchar2(18),
5 pdd date not null
6 )
7 partition by range (pdd)
8 (
9 partition par_2000 values less than (to_date('2001-01-01','yyyy-mm-dd')),
10 partition par_2001 values less than (to_date('2002-01-01','yyyy-mm-dd')),
11 partition par_2002 values less than (to_date('2003-01-01','yyyy-mm-dd')),
12 partition part_maxvalue values less than (maxvalue)
13 );
Table created.
--创建全局索引
SCOTT@ORA11GR2>create index idx_test_par on test_par(idcard);
Index created.
--插入几条测试数据,分别存放在不同的分区中
SCOTT@ORA11GR2>insert into test_par values(500,'2000',to_date('20000101','yyyymmdd'));
1 row created.
SCOTT@ORA11GR2>insert into test_par values(501,'2001',to_date('20010201','yyyymmdd'));
1 row created.
SCOTT@ORA11GR2>insert into test_par values(502,'2002',to_date('20020301','yyyymmdd'));
1 row created.
SCOTT@ORA11GR2>commit;
Commit complete.
--此时索引的状态为有效的
SCOTT@ORA11GR2>select INDEX_NAME,STATUS from user_indexes where index_name='IDX_TEST_PAR';
INDEX_NAME STATUS
------------------------------ --------
IDX_TEST_PAR VALID
--创建与分区表结构相同的表
SCOTT@ORA11GR2>create table test
2 (
3 nid number(10) constraint pk_test primary key,
4 idcard varchar2(18),
5 pdd date not null
6 );
Table created.
--插入数据:
SCOTT@ORA11GR2>insert into test select rownum,rpad(rownum,18,'0'),to_date('20020101','yyyymmdd')+rownum from dual connect by rownum<=100;
100 rows created.
SCOTT@ORA11GR2>commit;
Commit complete.
SCOTT@ORA11GR2>select min(pdd),max(pdd) from test;
MIN(PDD) MAX(PDD)
------------------- -------------------
2002-01-02 00:00:00 2002-04-11 00:00:00
SCOTT@ORA11GR2>select count(*) from test;
COUNT(*)
----------
100
--进行交换分区动作:
SCOTT@ORA11GR2>alter table test_par exchange partition par_2002 with table test;
Table altered.
--验证
--此时test表中,只有一条记录了。即原来2002分区中的数据。
SCOTT@ORA11GR2>select count(*) from test;
COUNT(*)
----------
1
SCOTT@ORA11GR2>select * from test;
NID IDCARD PDD
---------- ------------------ -------------------
502 2002 2002-03-01 00:00:00
--验证看到分区表已经是102条记录
SCOTT@ORA11GR2>select count(*) from test_par;
COUNT(*)
----------
102
--其中我们交换的par_2002分区为100条记录
SCOTT@ORA11GR2>select count(*) from test_par partition (par_2002);
COUNT(*)
----------
100
--此时索引已失效,因为是全局索引;
SCOTT@ORA11GR2>select INDEX_NAME,STATUS from user_indexes where index_name='IDX_TEST_PAR';
INDEX_NAME STATUS
------------------------------ --------
IDX_TEST_PAR UNUSABLE
——重建全局索引:
SCOTT@ORA11GR2>alter index idx_test_par rebuild;
Index altered.
SCOTT@ORA11GR2>select INDEX_NAME,STATUS from user_indexes where index_name='IDX_TEST_PAR';
INDEX_NAME STATUS
------------------------------ --------
IDX_TEST_PAR VALID