oracle之分割槽交換

liqilin0429發表於2012-08-31

利用分割槽交換,做表空間的遷移詳細具體步驟

第一步 建立表空間
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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章