有一個需求,将某業務表的某個時間點之前的記錄轉移到它的曆史表中。如果目前業務表不是基于這個業務時間點的分區表設定,那隻能insert再delete操作。這種轉移資料的方法非常非常低基礎。經常在初級的資料庫管理人員和開發人員的程式中出現。不是說這個方法不好,對于轉移的記錄數量在幾十幾百條,而轉移頻率高,轉移時間點随機的情況而言,這個方法還是挺管用的。但如果轉移的資料量一次數以百萬計的話,這種方法就顯得低效了。
是以,在Oracle資料庫開發中,對于這種大資料的轉移可以使用分區表交換技術實作。即使你一次轉移的資料量幾億甚至幾十億也沒有關系,轉移時間依然是毫秒級的。這個方法大體流程是這樣:
首先,你需要将目前表修改為分區表,找到分區字段很關鍵;其次,這個分區表的索引都建立成本地索引,全局索引就不要了,原因後面介紹;再次,建立一個對應的臨時非分區表,表結構和這個一樣;最後使用alter table table_name exchange partition Partition_name with table table_name_exchange;操作,将表分區所擁有資料的實際實體存儲空間段互相交換,這是指針級的操作。
這樣就完成了這個表分區資料的快速轉移。
就這個操作流程,做一個測試。
(miki西遊 @mikixiyou 原文連結: http://mikixiyou.iteye.com/blog/1773659)
第一步,準備環境
建立一張測試表SALE,它的分區字段是DOTIME,按照季度進行分區。
CREATE TABLE SALE
(
DOTIME DATE DEFAULT sysdate,
BILLID VARCHAR2(20 BYTE) NOT NULL,
FROMARREAR NUMBER(16,4) DEFAULT 0
)
PARTITION BY RANGE (DOTIME)
(
PARTITION PY11Q3 VALUES LESS THAN (TO_DATE(' 2011-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
LOGGING,
PARTITION PY11Q4 VALUES LESS THAN (TO_DATE(' 2012-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
LOGGING,
PARTITION PY12Q1 VALUES LESS THAN (TO_DATE(' 2012-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
LOGGING,
PARTITION PY12Q2 VALUES LESS THAN (TO_DATE(' 2012-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN'))
LOGGING,
PARTITION P_MAX VALUES LESS THAN (MAXVALUE)
LOGGING
)
;
再建立一張交換表,表的字段結構和分區表完全一緻。
create table SALE_exchange
(
DOTIME DATE DEFAULT sysdate,
BILLID VARCHAR2(20 BYTE) NOT NULL,
FROMARREAR NUMBER(16,4) DEFAULT 0
);
注意,分區表上的主鍵所屬的全局唯一索引不要了,改成SALE (BILLID,DOTIME)上的本地索引,這樣也能保證資料的一緻性。原來的主鍵字段billid必須放在前面,防止原來原來基于billid直接查詢操作的性能下降太多。
create unique index PK_SALE on SALE (BILLID,DOTIME) local;
本地分區索引建立完畢。
第二步,
檢查一下資料記錄情況。假設我們要将PY11Q3分區中的記錄轉移走。
select count(*) from SALE partition(PY11Q3);
select count(*) from SALE_exchange;
第三步,轉移資料
alter table SALE exchange partition PY11Q3 with table SALE_exchange;
一個指令,将分區段和表段的空間指針互相替換,就實作了這個分區表的業務資料的轉移工作。
第四步,檢查索引狀态
分區表這點不好,如果分區發生改變,如exchange,move,split等,那麼該分區上的本地索引分區就會失效,同時整個分區表上的全局索引也會失效。是以我最開始說全局索引需要撤銷了,就是這個道理。試想,如果這時還有全局索引存在,那它失效了,這就将影響到分區表的其他業務操作。
不管怎樣,都需要檢查一下索引狀态。
select index_name, partition_name, status
from user_ind_partitions
where status = 'UNUSABLE'
union all
select index_name, '' as partition_name, status
from user_indexes
where status = 'UNUSABLE';
這裡,本地分區索引的索引分區肯定失效了。原來exchange表上的索引也會失效。它們都需要重建。
分區索引的重建:
alter index PK_SALE rebuild partition PY11Q3;
alter index PK_SALE_EXCHANGE rebuild;
經過這樣的操作之後,曆史資料是從目前業務表移出來了,但它在一個臨時的孤立的表中。在現實業務中,這樣的資料是需要移動曆史表中。當然,如果你有轉換操作,你可以繼續使用insert 方法轉移。如果沒有,你還可以使用分區交換技術,将這個資料交換到曆史表中。
簡而言之,Oracle分區表技術在大資料量表的操作中建議經常使用,它的很多特性有助于我們開發出高效的應用程式。