Oracle快速删除表中重复数据——适用百万级数据
本文是针对部分字段重复的表,对于表中完全重复的数据可以使用distinct。
Oracle删除表中重复数据有多种方法,
网上较多的一种如下:
delete from gljyjl jl where (jl.djbbh,jl.bgsbh) in
(select djbbh,bgsbh from gljyjl group by djbbh,bgsbh having count(*) > 1)
and rowid not in (select min(rowid) from gljyjl group by djbbh,bgsbh having count(*)>1);
但此方法执行效率太低,表中有40多万条数据,重复数据有三万多。此方法执行了几个小时,还没结束。。。
通过查看该语句的执行计划,发现竟需要执行46个多小时!!!
无奈只能放弃此方法!
最终想到一种解决方案:可以先删除表中重复的一部分数据,也就是说分多次删除重复数据。
delete from gljyjl where rowid in (select min(rowid) from gljyjl group by djbbh,bgsbh having count(*) > 1);
该SQL语句很简单,通过djbbh,bgsbh两个字段进行分组,选取出这两个字段重复的记录,
获得每个分组中rowid最小的那条记录的rowid,然后把这条记录删除。
这样便可以把每组中重复的记录都删掉一条。
之后重复执行该条SQL语句,直到所有的重复记录全部删除完就可以了。
但如果每组中重复的数据有上千条,就需要重复执行该SQL语句上千次。
这样便会操作上千次了,不是太方便!
解决办法是编写存储过程,重复执行该SQL语句,直到受影响的SQL为0。
create or replace procedure deleteEquals
as
begin
loop
delete from gljyjl where rowid in (select min(rowid) from gljyjl group by djbbh,bgsbh having count(*) > 1);
dbms_output.put_line('删除了'||to_char(sql%rowcount)||'行');
exit when sql%rowcount = 0;
end loop;
end;
/
执行该存储过程!
exec deleteEquals();
该表中的重复数据便会全部删除!