oracle資料量650G的表(有分割槽)資料刪除方案(分割槽交換技術)
阿新 • • 發佈:2019-02-03
背景:650G的流程已辦記錄表太大,用delete刪除的話肯定是刪不動的,然後因為這個大表肯定是建了分割槽的,所以打算使用分割槽交換技術。
具體SQL如下:
------------------執行指令碼之前需要用資料泵把BPMS_RU_DONE_TASK匯出來------------------ ------------------執行指令碼過程中使用者無法使用上報流程,查詢流程跟蹤------------------ ------------------重要:SQL要一條條執行,千萬不要copy到命令視窗一下執行------------------ --先要把表rename的目的相對於把表離線,如果是線上的表很多操作是無法做的 drop table BPMS_RU_DONE_TASK_TEMP; --如果rename執行失敗,則不要往下執行 rename BPMS_RU_DONE_TASK to BPMS_RU_DONE_TASK_TEMP; --刪除索引的原因是索引也是佔空間的,如果表的資料清理了,索引會產生很多碎片 drop index IND_BRDT_ACTIVITY_INS_ID3; drop index IND_BRDT_CUR_NODE_INS_ID3; drop index IND_BRDT_MAIN_PROCESS_INS_ID3; drop index IND_BRDT_TRANS_ACTOR_ID3; alter table BPMS_RU_DONE_TASK_TEMP drop constraint PK_BPMS_RU_DONE_TASK3; drop index IND_PK_BPMS_RU_DONE_TASK3; --準備使用分割槽交換技術 create table BK0403BPMS_RU_DONE_TASK ( done_task_id VARCHAR2(40) not null, main_process_id VARCHAR2(40), cur_process_id VARCHAR2(40), cur_node_id VARCHAR2(40), cur_node_name VARCHAR2(60), main_process_ins_id VARCHAR2(40), cur_process_ins_id VARCHAR2(40), cur_node_ins_id VARCHAR2(40), activity_ins_id VARCHAR2(40), status NUMBER(2), trans_actor_id VARCHAR2(40), actor_name VARCHAR2(40), read_flag NUMBER(1), back_flag NUMBER(2), expiration TIMESTAMP(6), urge_time TIMESTAMP(6), urge_interval NUMBER(20), urge_flag NUMBER(1), note VARCHAR2(4000), note_type NUMBER(2), create_time TIMESTAMP(6), version NUMBER(20), task_complete_type NUMBER(2) default -1, revoke_back_flag NUMBER(1) default 1, modify_date TIMESTAMP(6) ); --要使用並行,BK0403BPMS_RU_DONE_TASK這個表裡面最初的記錄是需要保留的資料 --下面的業務邏輯需要相應的開發人員確認 alter table BK0403BPMS_RU_DONE_TASK nologging; alter session enable parallel dml; insert /*+ append parallel(16)*/ into BK0403BPMS_RU_DONE_TASK (done_task_id, main_process_id, cur_process_id, cur_node_id, cur_node_name, main_process_ins_id, cur_process_ins_id, cur_node_ins_id, activity_ins_id, status, trans_actor_id, actor_name, read_flag, back_flag, expiration, urge_time, urge_interval, urge_flag, note, note_type, create_time, version, task_complete_type, revoke_back_flag) select /*+ parallel(T,16) */ done_task_id, main_process_id, cur_process_id, cur_node_id, cur_node_name, main_process_ins_id, cur_process_ins_id, cur_node_ins_id, activity_ins_id, status, trans_actor_id, actor_name, read_flag, back_flag, expiration, urge_time, urge_interval, urge_flag, note, note_type, create_time, version, task_complete_type, revoke_back_flag FROM BPMS_RU_DONE_TASK_TEMP T WHERE T.MAIN_PROCESS_ID = 'oneAssetProcess' AND T.STATUS = 1; commit; alter session disable parallel dml; alter table BK0403BPMS_RU_DONE_TASK logging; --進行分割槽交換 alter table BPMS_RU_DONE_TASK_TEMP exchange partition P_ONEASSETPROCESS with table BK0403BPMS_RU_DONE_TASK; --使用並行建索引 create unique index INDU_BPMS_RU_DONE_TASK4 on BPMS_RU_DONE_TASK_TEMP (DONE_TASK_ID) Nologging parallel 16; alter table BPMS_RU_DONE_TASK_TEMP add constraint pk_BPMS_RU_DONE_TASK4 primary key (DONE_TASK_ID); create index IND_BRDT_ACTIVITY_INS_ID4 on BPMS_RU_DONE_TASK_TEMP (ACTIVITY_INS_ID) Nologging parallel 16; create index IND_BRDT_CUR_NODE_INS_ID4 on BPMS_RU_DONE_TASK_TEMP (CUR_NODE_INS_ID) Nologging parallel 16; create index IND_BRDT_MAIN_PROCESS_INS_ID4 on BPMS_RU_DONE_TASK_TEMP (MAIN_PROCESS_INS_ID) Nologging parallel 16; create index IND_BRDT_TRANS_ACTOR_ID4 on BPMS_RU_DONE_TASK_TEMP (TRANS_ACTOR_ID) Nologging parallel 16; --一定要關閉索引的並行,要不然,資料庫明天一定會hang住 alter index INDU_BPMS_RU_DONE_TASK4 noparallel; alter index IND_BRDT_ACTIVITY_INS_ID4 noparallel; alter index IND_BRDT_CUR_NODE_INS_ID4 noparallel; alter index IND_BRDT_MAIN_PROCESS_INS_ID4 noparallel; alter index IND_BRDT_TRANS_ACTOR_ID4 noparallel; alter table BPMS_RU_DONE_TASK_TEMP enable row movement; --收集統計資訊的命令要在命令視窗執行 exec dbms_stats.gather_table_stats(user,'BPMS_RU_DONE_TASK_TEMP',cascade => true,degree => 32,no_invalidate=>FALSE,estimate_percent=> 80); rename BPMS_RU_DONE_TASK_TEMP to BPMS_RU_DONE_TASK; --完成指令碼之後需要做驗證 1.下發和回退一個流程是否能成功。 2.檢查表和索引的並行度,如果沒有資料則是正常的,如果有資料則導回來 select s.table_name,s.degree from user_tables s where s.degree >1; 3.把各分割槽的資料導回來 select s.segment_name,s.partition_name,s.bytes/1024/1024/1024 from user_segments s where s.segment_name='BPMS_RU_DONE_TASK';