金蝶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 中彻底取代了第二个索引,应该去掉的.索引