ITPub博客

首页 > 数据库 > Oracle > 快速删除大量数据

快速删除大量数据

原创 Oracle 作者:1xian 时间:2009-04-22 14:06:16 0 删除 编辑
架构: 分布式系统,用AQ同步DML是实现动态数控的同步。

症状:中心数据库的queue里堆积大量的数据发布出去,知道撑爆tablespace。

观察: AQ job 在花大量的时间等待一个“wait for unread message on broadcast channel”事件。这是一个被定义为空闲的事件。[@more@]架构: 分布式系统,用AQ同步DML是实现动态数控的同步。

症状:中心数据库的queue里堆积大量的数据发布出去,知道撑爆tablespace。

观察: AQ job 在花大量的时间等待一个“wait for unread message on broadcast channel”事件。这是一个被定义为空闲的事件。

找遍了google,就发现这么一条比较有用的信息:

The Oracle process is waiting for a message on a broadcast channel. This is normally an idle wait - the process is waiting for an AQ message on a subscribed queue.
(http://dba.5341.com/msg/51714.html)

说明: 这并不仅仅是中心数据库的问题,而是整个系统的问题。

实际情况:

非主要业务。


动态数据的表:alarm,event,ev_combind,printable_event 都超过了百万,达到三四百万。不分区。

这几个表之间的关系是:

alarm =》event =》 ev_combined =》 printable_event
event =》 ev_combined =》 printable_event

=》代表trigger

这样的话,对于queue里的每一个DML,直到数据被trigger到
printable_event并返回,一个事物才算完成。
这样每一个子站的queue处理速度慢而影响了中心数据库queue的处理速度。

设计缺陷:

1). 对于每一个这样的表,平均每一个row实际的大小是330个bytes左右。换成是ascii的DML的话会更大。
2). 几个表的角色和之间的关系没有规划好,实际上是用trigger重复了大量的数据。
3). 没有合理的分区。
4). 完全不必要的constaints和index。
5). 错误的数据类型。本该用number,date,timestamp的地方全用成了varchar2.


临时的解决方法:
1)。删除中心数据库queue里的数据。
2)。清空所有子站的动态数据的表

长久的解决思路:

1)。重新定义基础数据的结构。这个不可能了。
2)。分区。待定。
3)。维持动态表的到一定的大小,只保持最近一段时间之内的数据。时间窗滚动前进。这涉及到了快速删除大量的数据。

思路来自两个地方:
1. LARGE DELETE快速删除 http://space.itpub.net/69204/viewspace-45358
2. 利用rowid快速在线更新海量数据 http://www.itpub.net/thread-1052077-1-2.html


思路2的方法是并行删除,用到parallel index, Oracle 9i 不支持。但是order by rowid 利用缓存的思路很可取。

思路1的方法是批量绑定(bulk binds)。

结合思路1和思路2, 最终结果:


----------------------------------------
create or replace procedure del_EV as
-- 1399883 / ((31 * 60) + 24) = 743.037686
-- 1398 883 / (32 * 33) = 1324.69981

type rtab is table of rowid index by binary_integer;
y rtab;
cursor x is select rowid from EV_COMBINED where createtime < sysdate - 2 order by rowid;

begin
open x ;
loop
fetch x bulk collect into y limit 1000;

forall i in 1 .. y.count
delete from EV_COMBINED where rowid = y(i);
commit;

exit when x%notfound;

end loop;
close x;
end;

/
show errors;

exec del_ev();

----------------------------------------


printable_event表根本没有数据类型为date或者timestamp的列。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/21342557/viewspace-1021058/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 搬家咯
请登录后发表评论 登录
全部评论

注册时间:2009-04-15

  • 博文量
    13
  • 访问量
    15890