一种批量删除数据的方法

这两天碰见一个比较紧急的生产问题,由于还在处理中,所以暂时不能给出整体描述,但其中涉及的一个问题就是删除一张大表中的过期历史数据,针对不同的类型的表可能有不同的解决方法,比如若是按照时间做的分区表,drop partition删除分区的操作可能是效率最快的、最简单的,若是一张普通表则需要有一些索引键值为删除条件,但需要注意的是最好做批量删除,且一次删除量不要太多,因为delete操作会将数据前镜像保存在UNDO回滚表空间,由于占用过多、事务过大、执行时间过长、UNDO空间过小等一系列问题存在,就有可能会影响正常的交易操作,这话题不是今天的主题。

删除历史数据可以使用存储过程,也可以写一个程序来做,区别是存储过程是直接在数据库中操作,少了客户端和数据库交互的环节,若是需要一些复杂的校验逻辑,可能写程序要更方便一些,但也不是绝对的,可能有人认为存储过程更好,无论什么方式,能解决问题才是最重要。

eygle大神曾经提供过一个用于批量删除数据的存储过程,在这引用下,版权还是eygle的:),(http://www.eygle.com/archives/2005/04/oracleoeouaeeae.html),强调的就是:分批删除,逐次提交。

create or replace procedure delBigTab
(
p_TableName       in    varchar2,
p_Condition       in    varchar2,
p_Count        in    varchar2
)
as
pragma autonomous_transaction;
n_delete number:=0;
begin
while 1=1 loop
EXECUTE IMMEDIATE
'delete from '||p_TableName||' where '||p_Condition||' and rownum <= :rn'
USING p_Count;
if SQL%NOTFOUND then
exit;
else
n_delete:=n_delete + SQL%ROWCOUNT;
end if;
commit;
end loop;
commit;
DBMS_OUTPUT.PUT_LINE('Finished!');
DBMS_OUTPUT.PUT_LINE('Totally '||to_char(n_delete)||' records deleted!');
end;
/

这是一可以有参数输入的存储过程,分别是:
p_TableName:待删除表的表名,
p_Condition:删除条件,
p_Count:一次删除的记录条数,rownum,
而且用了自治事务pragma autonomous_transaction,存储过程使用commit结尾。
整个逻辑很清晰和透彻,想必各位稍微看看都能明白。

这篇文章中(http://blog.csdn.net/xyjnzy/article/details/6194177)还介绍了另一种更精细的方法,判断日志是否已经归档了,避免数据删除快于日志归档的速度,如果发现尚未完成切换,则sleep一下,等待切换完成,再做下一次删除。

针对我这个需求,有一些可以改动的地方,由于这张表是一个按照NUMBER值做hash的哈希分区表,所以从效率上看,还可以精确至每个hash分区来做删除,这点是建荣给的建议,另外例子中自治事务我觉得也是可以不用的,因此针对SQL语句可以改为如下:

delete from table partition (p1) where insert_time<sysdate and rownum <= :rn;

即指定分区名称(这可以作为另一个参数),然后可以通过手工执行,依次用rn=100、1000、5000、10000等几个值来选择从时间和删除量可接受的范围。总结一下,
1.如果使用存储过程,或许可以不用自治事务。
2.可以将partition作为另一个参数。
3.由于这张表数据量太大,即使使用索引条件做count(*)操作时间都很久,因此暂时未知符合条件需要删除的记录条数,因此需要根据测试和时间需求,明确rownum使用的可行条数,选择小值则可能循环次数要多,选择大值则可能循环次数少,总之务必要分批删除、批量提交,避免delete子句对UNDO表空间的过大影响。

以上只是提供了删除历史记录的一种存储过程操作的方法,以及针对我的需求做的一些改进,至于会采用何种方法,可能还会根据得到的信息,有其他需要改进的地方,可能还会使用程序的方法,可能会使用这种存储过程,待完成后会再做总结了。

欢迎关注我的个人微信公众号:bisal的个人杂货铺

时间: 2024-10-22 03:05:25

一种批量删除数据的方法的相关文章

PHP批量删除数据的方法

PHP教程:研究批量删除数据的方法. SQL:$SQL="delete from `doing` where id in ('1,2,3,4')"; 数据用逗号隔开. 表单: <form action="?action=doing" method="post"> <input name="ID_Dele[]" type="checkbox" id="ID_Dele[]"

sql下三种批量插入数据的方法_MsSql

本文将介绍三种批量插入数据的方法.第一种方法是使用循环语句逐个将数据项插入到数据库中:第二种方法使用的是SqlBulkCopy,使您可以用其他源的数据有效批量加载 SQL Server 表:第三种使用的方法是sql server中的表值参数方法,表值参数是 SQL Server 2008 中的新参数类型.表值参数是使用用户定义的表类型来声明的.使用表值参数,可以不必创建临时表或许多参数,即可向 Transact-SQL 语句或例程(如存储过程或函数)发送多行数据.       代码示例:    

sql下三种批量插入数据的方法

本文将介绍三种批量插入数据的方法.第一种方法是使用循环语句逐个将数据项插入到数据库中:第二种方法使用的是SqlBulkCopy,使您可以用其他源的数据有效批量加载 SQL Server 表:第三种使用的方法是sql server中的表值参数方法,表值参数是 SQL Server 2008 中的新参数类型.表值参数是使用用户定义的表类型来声明的.使用表值参数,可以不必创建临时表或许多参数,即可向 Transact-SQL 语句或例程(如存储过程或函数)发送多行数据. 代码示例: 此例子为控制台输出

Oracle中大批量删除数据的方法_oracle

写一个循环删除的过程. create or replace procedure delBigTab(p_TableName in varchar2,p_Condition in varchar2,p_Count in varchar2)  as pragma autonomous_transaction; n_delete number:=0; begin  while 1=1 loop EXECUTE IMMEDIATE 'delete from '||p_TableName||' where

PHP 批量删除数据的方法分析_php技巧

大家可以参考下面的这篇文章http://www.jb51.net/article/6488.htmSQL:$SQL="delete from `doing` where id in ('1,2,3,4')"; 数据用逗号隔开. 表单: 复制代码 代码如下: <form action="?action=doing" method="post"> <input name="ID_Dele[]" type=&quo

sql批量删除数据的几种方法介绍

sql批量删除数据的几种方法介绍 a是A表的一列,存在a=1的数据 1.Delete from A where exists (Select 1 where a=1)  2.Delete from A where exists (Select 1 from A where a=1) 结果 1:只删除a=1一条数据,2:删除所有数据. ,里面的数据是yyyy.mm.dd格式的,另外由表单提交要删除的某一年的数据,该表单名为Year,我现在想通过一个SQL语句批量删除某一年的所有记录,比如删除所有该

asp批量删除数据的几种方法

批量删除数据方法一 id=request.form("checkbox") id=split(id,",") shu=0 for i=0 to ubound(id) sql="select * from jiang_fname where id="&id(i) set rs=conn.execute(sql) if not rs.eof then delete_file(rs("fname")) end if rs.c

asp 保存数据与批量删除数据方法

文章来提供一篇asp教程 保存数据与批量删除数据方法哦,在asp中保存数据到数据库教程也有很多种方法,我们只说了二种,同时删除数据也有很多方法,单条删除,批量删除,会用到for ,in来 实现. 注意:不同的字段名用英文逗号隔开,且不支持星号 表名处输入要查询的表名:如:table1 前台表单页面: 主要是注意input字段的name属性. asp下常用的添加数据代码是: 通过adodb.recordset 优点是:数据库入库比较简单,不用考虑单引号问题.不容易出现错误. 代码如下: usern

批量删除数据方法

在一个Oracle数据库运行过程中,有时候会遇到要批量删除数据的情况,如一个保存历史数据的表中有大量的数据已经不需要保留,要将这部分数据删除.通常采用的方法如下: 1.使用TRUNCATE命令进行删除. 如果是整个表的数据都要删除的话,使用TRUNCATE TABLE命令是理想的选择.它删除了表中的所有数据,并且因为不写REDO LOG FILE,所以速度很快.删除的同时,表的索引和约束条件仍然存在.这种方法适用于ORACLE的各个版本.但是当要删除的数据只是表中的一部分时,这种方法便行不通了.