Oracle 根據條件大量刪除數據

金蝶BOS裏系統表 t_bas_message 表用於存放系統消息.實際操做中,客戶端默認15分鐘查詢一次是否有新消息sql

用戶基本不會去刪除已讀的消息,這就致使這張表大得驚人,系統運行一年多以來,大約有 4500萬條數據.再加上這張表上存在索引,對數據庫而言,一旦操做失誤致使表中索引失效,數據庫會由於全表掃描太多完全卡死.數據庫

以後考濾刪除一個月之前的數據執行SQL語句以下less

DELETE FROM t_bas_message t WHERE t.fsendtime > Sysdate-30;

這段代碼在測試庫運行了兩個多小時.一方面是數據量很大,另外一方面是由於表中有幾列索引.實際中這種方案確定不行.測試


跟DBA討論了一下,有兩種方案.spa

A 經過表分區操做.經過表進行分區,而後直接刪除無關分區.代碼以下code

-- 建立中間表,添加主鍵,索引,分區等信息
create table T_BAS_MESSAGE_bak
(
  fid                VARCHAR2(44) not null
)
partition by range (fsendtime)
(
  partition PART_20141201 values less than (TIMESTAMP' 2014-12-01 00:00:00'),
  partition PART_MAX values less than (MAXVALUE)
);
--驗證是否能夠操做
CALL dbms_redefinition.can_redef_table('HLWL','T_BAS_MESSAGE');
--開始重定義
CALL dbms_redefinition.start_redef_table('HLWL', 'T_BAS_MESSAGE', 'T_BAS_MESSAGE_bak');
--同步表結構(這段只能在SQLPlus下執行,因此注掉了)
--set serverout on;
--declare
--  retval   number(5);
--begin
--  dbms_redefinition.copy_table_dependents (user,'bo_cr_sales_vbillcode','bo_cr_sales_vbillcode_20141111',ignore_errors=>TRUE,num_errors=>retval);
--  dbms_output.put_line(retval);
--end;
--/
--
--同步數據
CALL dbms_redefinition.sync_interim_table('HLWL', 'T_BAS_MESSAGE', 'T_BAS_MESSAGE_bak');
--在線重定義表
CALL dbms_redefinition.finish_redef_table('HLWL', 'T_BAS_MESSAGE', 'T_BAS_MESSAGE_bak');
--刪除中間表
DROP TABLE T_BAS_MESSAGE_bak;
--完全刪除表分區(這裏用表分區快速刪除數據)
ALTER TABLE T_BAS_MESSAGE DROP PARTITION PART_20150101;
--刪除表分區後添加約束,索引,若是放在前面,刪除會區會致使全局索引失效,包括主鍵索引
alter table T_BAS_MESSAGE add constraint PK_BAS_MCMESSAGE primary key (FID);
--從新採集表信息
CALL dbms_stats.gather_table_stats('HLWL','T_BAS_MESSAGE');


B 把有用的數據轉移到一張表,而後Drop 掉原表.從新建立原表後導入數據.代碼以下server

--t.fsender_l1<>'administrator'  包括 AND t.fsender_l1 is not null
CREATE TABLE t_bas_message_bak AS SELECT * FROM  t_bas_message t WHERE t.fsendtime> Sysdate-30 AND t.fsender_l1<>'administrator';
DROP TABLE t_bas_message;
CREATE TABLE t_bas_message AS SELECT * FROM  t_bas_message_bak;
create index IX_MESSAGE_TEXT on T_BAS_MESSAGE (FRECEIVER, FORGID);
create index IX_MSG_RECEIVER on T_BAS_MESSAGE (FRECEIVER);
create index IX_MSG_SOURCE on T_BAS_MESSAGE (FSOURCEID);
alter table T_BAS_MESSAGE
add constraint PK_BAS_BMCMESSAGE primary key (FID);
DROP TABLE t_bas_message_bak;

PS:這裏的三個索引,是原表就有的,因此加上.但實際上我認爲,第一個組合索引在Oracle 中徹底取代了第二個索引,應該去掉的.索引

相關文章
相關標籤/搜索