删除oracle表中的重复记录:大小为389 GB

时间:2013-11-02 07:39:46

标签: sql database oracle truncate

需要从表中删除重复记录。表中包含33列,只有PK_NUM是主键列。由于PK_NUM包含唯一记录,我们需要考虑最小值/最大值。

  1. 表中的总记录:1766799022
  2. 表中不同的记录:69237983
  3. 表格中的重复记录:1697561039
  4. 列详细信息:

    • 4:日期数据类型
    • 4:数字数据类型
    • 1:字符数据类型
    • 24:Varchar2数据类型

    表格大小:386 GB

    数据库详细信息:Oracle Database 11g EE :: 11.2.0.2.0 :: 64bit Production

    示例数据:

    • col1,col2,col3
    • 1,ABC,123
    • 2,PQR,456
    • 3,ABC,123

    预期数据应仅包含2条记录:

    • col1,col2,col3
    • 1,ABC,123
    • 2,PQR,456

    * 1可以替换为3,反之亦然。

    我的计划是

    1. 拉出不同的记录并将其存储在备份表中(即使用insert into select)
    2. 截断现有表格并将记录从备份移至现有。
    3. 由于数据量巨大,

      1. 想知道用于检索distinct的优化sql是什么 记录
      2. 任何估计需要多少才能完成(插入 选择)并截断现有表格。
      3. 请告诉我,如果有其他最好的方法可以实现这一点。我的最终目标是删除重复项。

2 个答案:

答案 0 :(得分:2)

使这种内存有效的一个选项是将所有行插入(nologging append)到一个表中,该表在要检测重复项的列的列表上进行散列分区,或者如果数量有限制然后使用尽可能多的列(旨在使用具有最大选择性的列)。使用类似1024个分区的东西,理想情况下每个分区都在

然后,您已将每行的所有潜在重复项隔离到同一分区中,并且重复数据删除的标准方法将在每个分区上运行,而不会占用大量内存。

因此,对于每个分区,您可以执行类似...

的操作
insert /*+ append */ into new_table
select *
from   temp_table partition (p1) t1
where  not exists (
         select null
         from   temp_table partition (p1) t2
         where  t1.col1 = t2.col1 and
                t1.col2 = t2.col2 and
                t1.col3 = t2.col3 and
                ... etc ...
                t1.rownum < t2.rownum);

这里表现良好的关键是,为了在该查询中执行反连接而创建的哈希表(几乎与分区本身一样大)能够适合内存。因此,如果您可以管理2GB排序区域,则至少需要389/2 =大约200个表分区。舍入到最接近的2的幂,所以在这种情况下使其成为256个表分区。

答案 1 :(得分:1)

试试这个:

rename table_name to table_name_dup;

然后:

create table table_name 
as
select 
  min(col1)
, col2
, col3
from table_name_dup
group by 
  col2
, col3;

据我所知,所使用的temp_tablespace并不像整个group by在将要创建新表的目标表空间中发生的那样多。完成后,您可以删除带有重复项的那个:

drop table table_name_dup;