oracle之分区交换

利用分区交换,做表空间的迁移详细具体步骤

第一步 创建表空间
SQL> alter system set db_create_file_dest='D:\APP\ADMINISTRATOR\ORADATA\QILIN';

系统已更改。


SQL> create tablespace ts_sales_2009_1 datafile size 10M autoextend on;

表空间已创建。

其中第一条语句是设定一个数据文件存放路径,让Oracle自动在该路径下创建文件,
并使用Oracle自己的方式为数据文件命名。

SQL> select file_name,tablespace_name from dba_data_files;

FILE_NAME                                TABLESPACE_NAME
---------------------------------------- ------------------------------
D:\APP\ADMINISTRATOR\ORADATA\QILIN\USERS USERS
01.DBF

D:\APP\ADMINISTRATOR\ORADATA\QILIN\UNDOT UNDOTBS1
BS01.DBF

D:\APP\ADMINISTRATOR\ORADATA\QILIN\SYSAU SYSAUX
X01.DBF

D:\APP\ADMINISTRATOR\ORADATA\QILIN\SYSTE SYSTEM
M01.DBF

D:\APP\ADMINISTRATOR\ORADATA\QILIN\EXAMP EXAMPLE
LE01.DBF

D:\APP\ADMINISTRATOR\ORADATA\QILIN\QILIN TS_SALES_2009_1
\DATAFILE\O1_MF_TS_SALES_83S1MHYL_.DBF

D:\APP\ADMINISTRATOR\ORADATA\QILIN\QILIN TS_SALES_2009_2
\DATAFILE\O1_MF_TS_SALES_83S1NSVZ_.DBF


FILE_NAME                                TABLESPACE_NAME
---------------------------------------- ------------------------------
D:\APP\ADMINISTRATOR\ORADATA\QILIN\QILIN TS_SALES_2009_3
\DATAFILE\O1_MF_TS_SALES_83S1O0PC_.DBF

D:\APP\ADMINISTRATOR\ORADATA\QILIN\QILIN TS_SALES_2009_4
\DATAFILE\O1_MF_TS_SALES_83S1O80W_.DBF

D:\APP\ADMINISTRATOR\ORADATA\QILIN\QILIN TS_SALES_2009_5
\DATAFILE\O1_MF_TS_SALES_83S1OL63_.DBF

D:\APP\ADMINISTRATOR\ORADATA\QILIN\QILIN TS_SALES_2009_6
\DATAFILE\O1_MF_TS_SALES_83S1ORBS_.DBF


已选择11行。

第二步 创建分区表 conn scott/qilin
create table sale_data
(
sales_id number(5),
salesman_name varchar2(30),
sales_amount number(10),
sales_date date
)
partition by range(sales_date)
(
partition sales_2009_1 values less than(to_date('01/01/2009','DD/MM/YYYY')) tablespace ts_sales_2009_1,
partition sales_2009_2 values less than(to_date('01/02/2009','DD/MM/YYYY')) tablespace ts_sales_2009_2,
partition sales_2009_3 values less than(to_date('01/03/2009','DD/MM/YYYY')) tablespace ts_sales_2009_3,
partition sales_2009_4 values less than(to_date('01/04/2009','DD/MM/YYYY')) tablespace ts_sales_2009_4,
partition sales_2009_5 values less than(to_date('01/05/2009','DD/MM/YYYY')) tablespace ts_sales_2009_5,
partition sales_2009_6 values less than(to_date('01/06/2009','DD/MM/YYYY')) tablespace ts_sales_2009_6,
partition sales_2009_7 values less than(to_date('01/07/2009','DD/MM/YYYY')) tablespace ts_sales_2009_7,
partition sales_2009_8 values less than(to_date('01/08/2009','DD/MM/YYYY')) tablespace ts_sales_2009_8,
partition sales_2009_9 values less than(to_date('01/09/2009','DD/MM/YYYY')) tablespace ts_sales_2009_9,
partition sales_2009_10 values less than(to_date('01/10/2009','DD/MM/YYYY')) tablespace ts_sales_2009_10,
partition sales_2009_11 values less than(to_date('01/11/2009','DD/MM/YYYY')) tablespace ts_sales_2009_11,
partition sales_2009_12 values less than(to_date('01/12/2009','DD/MM/YYYY')) tablespace ts_sales_2009_12,
partition sales_2010_1 values less than(to_date('01/01/2010','DD/MM/YYYY')) tablespace ts_sales_2010_1
);


第三步 创建索引
create index indsale_data on sale_data(sales_date)
local
(
partition sales_2009_1 tablespace ts_sales_2009_1,
partition sales_2009_2 tablespace ts_sales_2009_2,
partition sales_2009_3 tablespace ts_sales_2009_3,
partition sales_2009_4 tablespace ts_sales_2009_4,
partition sales_2009_5 tablespace ts_sales_2009_5,
partition sales_2009_6 tablespace ts_sales_2009_6,
partition sales_2009_7 tablespace ts_sales_2009_7,
partition sales_2009_8 tablespace ts_sales_2009_8,
partition sales_2009_9 tablespace ts_sales_2009_9,
partition sales_2009_10 tablespace ts_sales_2009_10,
partition sales_2009_11 tablespace ts_sales_2009_11,
partition sales_2009_12 tablespace ts_sales_2009_12,
partition sales_2010_1 tablespace ts_sales_2010_1
);

第四步 查看每个分区和分区索引都创建在各自的表空间上了
select partition_name,segment_type,tablespace_name from user_segments where
segment_name in('SALE_DATA','INDSALE_DATA')

第五步 检查表空间是否符合以表空间传递的方式导出 conn /as sysdba
SQL> exec dbms_tts.transport_set_check('ts_sales_2009_1',TRUE);

PL/SQL 过程已成功完成。

SQL> select * from transport_set_violations;

VIOLATIONS
-------------------------------------------------------------------------------

ORA-39921: 默认分区 (表) 表空间 USERS (对于 SALE_DATA) 未包含在可传输集内。
ORA-39901: 分区表 SCOTT.SALE_DATA 部分包含在可传输集内。

上面的信息显示了我们要传递的表空间有两点不符合传递要求:
●分区表的默认表空间没有包含在传递的表空间。
●表分区还有其他的分区,没有在要传递的表空间上。
基于以上两点原因,我们不能直接对分区的表空间进行移植,而这种数据存储的设计是合理的,所以我们需要考虑使用其他的方式来解决这个问题。

幸运的是,我们找到了一种方法,那就是分区交换。它的方法是这样的:
●创建一个临时表;
●在临时表上创建索引;
●将需要导出的分区数据和分区索引与临时表进行分区交换;
●将临时表和索引所在的表空间导出。


select partition_name,tablespace_name,segment_type from user_segments where segment_name='INDSALE_DATA';
select partition_name,tablespace_name,segment_type from user_segments where segment_name='SALE_DATA'


第六步 创建临时表,并创建索引 conn scott/qilin
create table tmp_sale_data_2009_1 as select * from sale_data where 1=2;
create index ind_temp_sale_data_2009_1 on tmp_sale_data_2009_1(sales_date);
insert into tmp_sale_data_2009_1 values(11,'qilin',5,to_date('2009-01-06','yyyy-mm-dd'));
最初的时候,我们看到临时表和临时表的索引都默认存放在USERS表空间上(在11G上必须先插入一行数据才可以,否则查询不出来,但是如果在DBA的权限下创建,却可以查询到具体的信息)
  1* select tablespace_name,segment_name,segment_type from user_segments where segment_name like '%SALE_DATA_2009_1'
SQL> /

TABLESPACE_NAME                SEGMENT_NAME                   SEGMENT_TYPE
------------------------------ ------------------------------ ------------------

USERS                        TMP_SALE_DATA_2009_1            TABLE
USERS                         IND_TEMP_SALE_DATA_2009_1      INDEX


conn /as sysdba
SQL> create table tmp_sale_data_2009_1 as select * from scott.sale_data where 1=
2;

表已创建。

SQL> create index IND_TMP_SALE_DATA_2009_1 on TMP_SALE_DATA_2009_1(SALES_DATE);

索引已创建。

 

SQL>select tablespace_name,segment_name,segment_type from user_segments where s
egment_name like '%SALE_DATA_2009_1'
SQL> /

TABLESPACE_NAME                SEGMENT_NAME                   SEGMENT_TYPE
------------------------------ ------------------------------ ------------------

SYSTEM                         TMP_SALE_DATA_2009_1           TABLE
SYSTEM                         IND_TMP_SALE_DATA_2009_1       INDEX

第七步  向交换的分区表中插入数据
SQL> begin
     for i in 1..10000 loop
       insert into sale_data values(i,'qilin',i*5,to_date('2009-01-06','yyyy-mm-dd'));
    end loop;
    commit;
    end;
    /

PL/SQL 过程已成功完成。


SQL> select count(*) from sale_data;

  COUNT(*)
----------
     10000

SQL> select count(*) from sale_data partition(sales_2009_2);

  COUNT(*)
----------
     10000
可以看到,要交换的分区SALES_2009_2包含了10000条记录。

第八步 开始进行分区交换,包括分区索引,一并交换到临时表上表已更改。
SQL> alter table sale_data exchange partition sales_2009_2
                           with table tmp_sale_data_2009_2
                           including indexes with validation;

第九步 完成了分区交换,下面我们来看看各个对象所在的表空间情况
elect partition_name,tablespace_name,segment_type from user_segments where segment_name='SALE_DATA' OR segment_name='INDSALE_DATA' order by 2;

PARTITION_NAME                 TABLESPACE_NAME                SEGMENT_TYPE
------------------------------ ------------------------------ ------------------

SALES_2009_2                   SYSTEM                         INDEX PARTITION
SALES_2009_2                   SYSTEM                         TABLE PARTITION
SALES_2009_1                   TS_SALES_2009_1                INDEX PARTITION
SALES_2009_1                   TS_SALES_2009_1                TABLE PARTITION
SALES_2009_3                   TS_SALES_2009_3                TABLE PARTITION
SALES_2009_3                   TS_SALES_2009_3                INDEX PARTITION
SALES_2009_4                   TS_SALES_2009_4                INDEX PARTITION
SALES_2009_4                   TS_SALES_2009_4                TABLE PARTITION
SALES_2009_5                   TS_SALES_2009_5                TABLE PARTITION
SALES_2009_5                   TS_SALES_2009_5                INDEX PARTITION
SALES_2009_6                   TS_SALES_2009_6                TABLE PARTITION

PARTITION_NAME                 TABLESPACE_NAME                SEGMENT_TYPE
------------------------------ ------------------------------ ------------------

SALES_2009_6                   TS_SALES_2009_6                INDEX PARTITION

已选择12行。
分区SALES_2009_2和相应的分区索引,已经交换到了SYSTEM表空间上;

SQL> select tablespace_name,segment_name,segment_type from user_segments where s
egment_name like '%SALE_DATA_2009_2';

TABLESPACE_NAME                SEGMENT_NAME                   SEGMENT_TYPE
------------------------------ ------------------------------ ------------------

TS_SALES_2009_2                TMP_SALE_DATA_2009_2           TABLE
TS_SALES_2009_2                IND_TEMP_SALE_DATA_2009_2      INDEX

而临时表TMP_SALE_DATA_2009_2和它的索引IND_TMP_SALE_DATA_2009_2交换到了以前分区所在的表空间TS_SALES_2009_2上。

第十步 查看分区交换后临时表的信息
SQL> select count(*) from sale_data;

  COUNT(*)
----------
         0

SQL> select count(*) from sale_data partition(sales_2009_2);

  COUNT(*)
----------
         0

SQL> select count(*) from tmp_sale_data_2009_2;

  COUNT(*)
----------
     10000


这样就完成了表空间的交换,表空间TS_SALES_2009_1上面的对象就是只有一个自包
含的表TMP_SALE_DATA_2009_1。

第十一步 表空间TS_SALES_2009_1上面的对象就是只有一个自包含的表TMP_SALE_DATA_2009_1。可以通过下面的操作来验证它 conn /as sysdba
SQL> exec dbms_tts.transport_set_check('TS_SALES_2009_2',TRUE);

PL/SQL 过程已成功完成。

SQL> select * from transport_set_violations;

未选定行

我们看到,transport_set_violations表中没有数据,说明空间已经通过了检查,可以
进行表空间传递操作了。

第十二步 进行表空间传递导出前,需要将要操作的表空间设置为只读
SQL> alter tablespace ts_sales_2009_2 read only;

表空间已更改。

第十三步 利用数据泵 导出数据
SQL> create directory demo as 'D:\qilin';

目录已创建。

SQL> grant read,write on directory demo to system;

授权成功。


C:\Users\Administrator>expdp system/qilin directory=demo dumpfile=tts.dmp transp
ort_tablespaces=TS_SALES_2009_2 TRANSPORT_FULL_CHECK=y logfile=tts.log

查询出导出表空间所在的数据文件名称
SQL> col file_name format a60;
SQL> select file_name, tablespace_name from dba_data_files where tablespace_name
='TS_SALES_2009_2';

FILE_NAME
------------------------------------------------------------
TABLESPACE_NAME
------------------------------
D:\APP\ADMINISTRATOR\ORADATA\QILIN\QILIN\DATAFILE\O1_MF_TS_S
ALES_83VH8PK2_.DBF
TS_SALES_2009_2

第十四步 导入数据
A 导出的文件复制到离线数据库服务器上。
D 同时将导出的那个表空间的对应的数据文件也复制到离线数据库服务器上
C 在离线数据库中,首先要创建好需要导入的分区表,并且要创建相应的索引。
创建分区表
create table sale_data
(
sales_id number(5),
salesman_name varchar2(30),
sales_amount number(10),
sales_date date
)
partition by range(sales_date)
(
partition sales_2009_1 values less than(to_date('01/01/2009','DD/MM/YYYY')) ,
partition sales_2009_2 values less than(to_date('01/02/2009','DD/MM/YYYY')) ,
partition sales_2009_3 values less than(to_date('01/03/2009','DD/MM/YYYY')) ,
partition sales_2009_4 values less than(to_date('01/04/2009','DD/MM/YYYY')) ,
partition sales_2009_5 values less than(to_date('01/05/2009','DD/MM/YYYY')) ,
partition sales_2009_6 values less than(to_date('01/06/2009','DD/MM/YYYY')) ,
partition sales_2009_7 values less than(to_date('01/07/2009','DD/MM/YYYY')) ,
partition sales_2009_8 values less than(to_date('01/08/2009','DD/MM/YYYY')) ,
partition sales_2009_9 values less than(to_date('01/09/2009','DD/MM/YYYY')) ,
partition sales_2009_10 values less than(to_date('01/10/2009','DD/MM/YYYY')) ,
partition sales_2009_11 values less than(to_date('01/11/2009','DD/MM/YYYY')) ,
partition sales_2009_12 values less than(to_date('01/12/2009','DD/MM/YYYY')) ,
partition sales_2010_1 values less than(to_date('01/01/2010','DD/MM/YYYY'))
);

创建索引
create index indsale_data on sale_data(sales_date)
local
(
partition sales_2009_1 ,
partition sales_2009_2 ,
partition sales_2009_3 ,
partition sales_2009_4 ,
partition sales_2009_5 ,
partition sales_2009_6 ,
partition sales_2009_7 ,
partition sales_2009_8 ,
partition sales_2009_9 ,
partition sales_2009_10 ,
partition sales_2009_11 ,
partition sales_2009_12 ,
partition sales_2010_1
);
直接创建在默认的表空间上就可以,因为这些分区都是空的

E 导入数据
C:\Users\Administrator>impdp system/qilin@WNPMPBJ directory=demo dumpfile=tts.dmp transport_datafiles='D:\APP\ADMINISTRATOR\ORADATA\WNPMPBJ\WNPMPBJ\DATAFILE\O1_MF_TS_SALES_83VH8PK2_.DBF' logfile=tts.log
Import: Release 11.2.0.1.0 - Production on 星期三 8月 29 17:51:16 2012
Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.
连接到: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
已成功加载/卸载了主表 "SYSTEM"."SYS_IMPORT_TRANSPORTABLE_01"
启动 "SYSTEM"."SYS_IMPORT_TRANSPORTABLE_01":  system/********@WNPMPBJ directory=
demo dumpfile=tts.dmp transport_datafiles='D:\APP\ADMINISTRATOR\ORADATA\WNPMPBJ\
WNPMPBJ\DATAFILE\O1_MF_TS_SALES_83VH8PK2_.DBF' logfile=tts.log
处理对象类型 TRANSPORTABLE_EXPORT/PLUGTS_BLK
处理对象类型 TRANSPORTABLE_EXPORT/TABLE
处理对象类型 TRANSPORTABLE_EXPORT/INDEX
处理对象类型 TRANSPORTABLE_EXPORT/INDEX_STATISTICS
处理对象类型 TRANSPORTABLE_EXPORT/POST_INSTANCE/PLUGTS_BLK
作业 "SYSTEM"."SYS_IMPORT_TRANSPORTABLE_01" 已于 17:51:19 成功完成

第十五步:查询导入离线数据库的的数据信息(临时表和表空间以及表中的数据都导入到了离线数据库中。conn scott/qilin)
SQL> col segment_name for a30;
SQL> select tablespace_name,segment_name,segment_type from user_segments
  2  where segment_name like '%SALE_DATA_2009_2';
 
TABLESPACE_NAME                SEGMENT_NAME                                                                     SEGMENT_TYPE
------------------------------ -------------------------------------------------------------------------------- ------------------
TS_SALES_2009_2                TMP_SALE_DATA_2009_2                                                             TABLE
TS_SALES_2009_2                IND_TMP_SALE_DATA_2009_2                                                         INDEX

此时离线数据库中分区及索引所在的表空间情况如下:
SQL> select partition_name,tablespace_name,segment_type from user_segments
  2  where segment_name = 'SALE_DATA'or segment_name='INDSALE_DATA'order by 2;
 
PARTITION_NAME                 TABLESPACE_NAME                SEGMENT_TYPE
------------------------------ ------------------------------ ------------------
SALES_2009_1                   USERS_BJT                      INDEX PARTITION
SALES_2010_1                   USERS_BJT                      TABLE PARTITION
SALES_2009_11                  USERS_BJT                      INDEX PARTITION
SALES_2009_12                  USERS_BJT                      INDEX PARTITION
SALES_2009_2                   USERS_BJT                      INDEX PARTITION
SALES_2009_3                   USERS_BJT                      INDEX PARTITION
SALES_2009_4                   USERS_BJT                      INDEX PARTITION
SALES_2009_5                   USERS_BJT                      INDEX PARTITION
SALES_2009_6                   USERS_BJT                      INDEX PARTITION
SALES_2009_7                   USERS_BJT                      INDEX PARTITION
SALES_2009_8                   USERS_BJT                      INDEX PARTITION
SALES_2009_9                   USERS_BJT                      INDEX PARTITION
SALES_2010_1                   USERS_BJT                      INDEX PARTITION
SALES_2009_1                   USERS_BJT                      TABLE PARTITION
SALES_2009_10                  USERS_BJT                      TABLE PARTITION
SALES_2009_11                  USERS_BJT                      TABLE PARTITION
SALES_2009_12                  USERS_BJT                      TABLE PARTITION
SALES_2009_2                   USERS_BJT                      TABLE PARTITION
SALES_2009_3                   USERS_BJT                      TABLE PARTITION
SALES_2009_4                   USERS_BJT                      TABLE PARTITION
 
PARTITION_NAME                 TABLESPACE_NAME                SEGMENT_TYPE
------------------------------ ------------------------------ ------------------
SALES_2009_5                   USERS_BJT                      TABLE PARTITION
SALES_2009_6                   USERS_BJT                      TABLE PARTITION
SALES_2009_7                   USERS_BJT                      TABLE PARTITION
SALES_2009_8                   USERS_BJT                      TABLE PARTITION
SALES_2009_9                   USERS_BJT                      TABLE PARTITION
SALES_2009_10                  USERS_BJT                      INDEX PARTITION
 
26 rows selected

查看离线表中的数据
SQL> select count(*) from tmp_sale_data_2009_2;
 
  COUNT(*)
----------
     10000
 
SQL> select count(*) from sale_data;
 
  COUNT(*)
----------
         0

第十六步 将导入的临时表交换到离线数据库的分区表中
alter table sale_data exchange partition sales_2009_2
                      with table tmp_sale_data_2009_2
                      including  indexes with validation;

第十七步 再次查看交换后的表的信息
SQL> select tablespace_name,segment_name,segment_type from user_segments
  2  where segment_name like '%SALE_DATA_2009_2';
 
TABLESPACE_NAME                SEGMENT_NAME                                                                     SEGMENT_TYPE
------------------------------ -------------------------------------------------------------------------------- ------------------
USERS_BJT                      TMP_SALE_DATA_2009_2                                                             TABLE
USERS_BJT                      IND_TMP_SALE_DATA_2009_2                                                         INDEX
 
以下说明传递过来的表空间TS_SALES_2009_2上的数据和索引已经交换到了离线数据库的分区SALES_2009_2上。
SQL> select partition_name,tablespace_name,segment_type from user_segments
  2  where segment_name = 'SALE_DATA'or segment_name='INDSALE_DATA'order by 2;
 
PARTITION_NAME                 TABLESPACE_NAME                SEGMENT_TYPE
------------------------------ ------------------------------ ------------------
SALES_2009_2                   TS_SALES_2009_2                INDEX PARTITION
SALES_2009_2                   TS_SALES_2009_2                TABLE PARTITION
SALES_2009_11                  USERS_BJT                      INDEX PARTITION
SALES_2009_12                  USERS_BJT                      INDEX PARTITION
SALES_2009_3                   USERS_BJT                      INDEX PARTITION
SALES_2009_4                   USERS_BJT                      INDEX PARTITION
SALES_2009_5                   USERS_BJT                      INDEX PARTITION
SALES_2009_6                   USERS_BJT                      INDEX PARTITION
SALES_2009_7                   USERS_BJT                      INDEX PARTITION
SALES_2009_8                   USERS_BJT                      INDEX PARTITION
SALES_2009_9                   USERS_BJT                      INDEX PARTITION
SALES_2010_1                   USERS_BJT                      INDEX PARTITION
SALES_2009_1                   USERS_BJT                      TABLE PARTITION
SALES_2009_10                  USERS_BJT                      TABLE PARTITION
SALES_2009_11                  USERS_BJT                      TABLE PARTITION
SALES_2009_12                  USERS_BJT                      TABLE PARTITION
SALES_2009_3                   USERS_BJT                      TABLE PARTITION
SALES_2009_4                   USERS_BJT                      TABLE PARTITION
SALES_2009_5                   USERS_BJT                      TABLE PARTITION
SALES_2009_6                   USERS_BJT                      TABLE PARTITION
 
PARTITION_NAME                 TABLESPACE_NAME                SEGMENT_TYPE
------------------------------ ------------------------------ ------------------
SALES_2009_7                   USERS_BJT                      TABLE PARTITION
SALES_2009_8                   USERS_BJT                      TABLE PARTITION
SALES_2009_9                   USERS_BJT                      TABLE PARTITION
SALES_2010_1                   USERS_BJT                      TABLE PARTITION
SALES_2009_1                   USERS_BJT                      INDEX PARTITION
SALES_2009_10                  USERS_BJT                      INDEX PARTITION
 
26 rows selected

第十八步 在离线数据库上查看临时表的数据信息和分区表的数据信息
SQL> select count(*) from tmp_sale_data_2009_2;
SQL>
 
  COUNT(*)
----------
         0
 
SQL> select count(*) from sale_data;
 
  COUNT(*)
----------
     10000
临时表中已经没有了数据,而以前空的分区现在有了10000条从在线数据库中传递过来的数据。

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/20976446/viewspace-742328/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/20976446/viewspace-742328/

你可能感兴趣的:(数据库)