需要从表中删除重复的记录。表包含 33 列,其中只有 PK_NUM
是主键列。由于 PK_NUM
包含唯一记录,我们需要考虑最小值/最大值。
- 表中记录总数:1766799022
- 表中的不同记录:69237983
- 表中有重复记录:1697561039
列详细信息:
- 4:日期数据类型
- 4:数字数据类型
- 1 : 字符数据类型
- 24 : Varchar2 数据类型
表的大小:386 GB
数据库详细信息:Oracle 数据库 11g EE::11.2.0.2.0::64 位生产
示例数据:
- col1 ,col2,col3
- 1,ABC,123
- 2,PQR,456
- 3,ABC,123
预期数据应仅包含 2 条记录:
- col1,col2,col3
- 1,ABC,123
- 2,PQR,456
*1可以换成3,反之亦然。
我的计划是
- 提取不同的记录并将其存储在备份表中。(即通过使用 insert into select)
- 截断现有表并将记录从备份移动到现有表。
由于数据量巨大,
- 想知道什么是用于检索不同的优化的 sql 记录
- 对完成所需时间的任何估计(插入 选择)并截断现有表。
如果有任何其他最佳方法可以实现此目的,请务必告诉我。我的最终目标是删除重复项。
最佳答案
使此内存有效的一个选项是将所有行插入(无日志追加)到一个表中,该表在要检测重复项的列列表上进行散列分区,或者如果对数量有限制然后使用尽可能多的列(旨在使用具有最大选择性的列)。使用 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 个表分区。
关于sql - 删除oracle表: size is 389 GB中的重复记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19739926/