我正在研究oracle 9i。我有一个包含135,000,000条记录的表,分区每个分区大约有。 10,000,000行。所有索引和一切。
我需要从中删除大约70,000,000行作为新业务要求。
所以我创建了要删除的行的备份作为单独的表。
Table1 <col1, col2........> -- main table (135,000,000 rows)
Table2 <col1, col2........> -- backup table (70,000,000 rows)
尝试了以下删除查询。
Delete from table1 t1 where exists (select 1 from table2 t2 where t2.col1 = t1.col1)
但需要无限时间。
然后尝试了
declare
cursor c1 is
select col1 from table2;
c2 c1%rowtype;
cnt number;
begin
cnt :=0;
open c1;
loop
fetch c1 into c2;
exit when c1%notfound;
delete from table1 t1 where t1.col1 = c2.col1;
if cnt >= 100000 then
commit;
end if;
cnt:=cnt+1;
end loop;
close c1;
end;
即使它已经运行了超过12个小时。但仍未完成。
请注意,table1上有多个索引,table2上有col1索引。分析所有表和索引。
请告知是否有任何优化方案。
谢谢你们。
答案 0 :(得分:4)
删除所有索引(备份create语句) 使用用于构建备份表的select语句,从中创建DELETE命令 重新创建所有索引
答案 1 :(得分:4)
我记得早些时候面对这个问题。在这种情况下,我们采取这样做,因为它比任何其他删除操作更快地运行:
1)创建另一个结构相同的表
2)将要保留的记录插入新表中(使用直接路径插入来加快速度)
3)放下旧桌子
4)重命名新表
答案 2 :(得分:1)
你说表是分区的。您是否打算删除某些分区中的所有数据?如果是这样,您应该能够简单地删除具有您想要删除的7000万行的7个分区。不过,我假设您的问题并非如此简单。
如果您可以进行临时提交,这意味着您并不关心事务一致性,那么最有效的方法可能就像
一样。CREATE TABLE rows_to_save
AS SELECT *
FROM table1
WHERE <<criteria to select the 65 million rows you want to keep>>
TRUNCATE TABLE table1;
INSERT /*+ append */
INTO table1
SELECT *
FROM rows_to_save;
除非创建备份表,否则简单发布DELETE
语句
DELETE FROM table1
WHERE <<criteria to select the 70 million rows you want to keep>>
在运行DELETE
之前,您还可以从删除或禁用索引和约束中受益。
答案 3 :(得分:0)
我会回答这个问题,假设过滤掉备份表的成本更低,但是使用你用来填充备份表的标准的否定可能会更便宜。
1)创建一个具有相同结构的新表。没有索引,约束或触发器。
2)
select 'insert /*+ append nologging */ into new_table partition (' || n.partition_name || ') select * from old_table partition (' || o.partition_name || ') minus select * from bak_table partition (' || b.partition_name || ');' from all_tab_partitions o, all_tab_partitions n, all_tab_partitions b where o.partition_no = all( n.partition_no, b.partition_no) and o.table_name = 'OLD_TABLE' and o.table_owner = 'OWNER' and n.table_name = 'NEW_TABLE' and n.table_owner = 'OWNER' and b.table_name = 'BAK_TABLE' and b.table_owner = 'OWNER'; -- note, I haven't run this it may need minor corrections in addition to the obvious substitutions
3)验证并运行上一个查询的结果
4)根据需要构建索引,约束和触发器
与删除相比,这避免了大量的重做和撤消。 附加提示直接路径插入 没有记录进一步减少重做 - 请确保您之后备份 利用您的分区将工作分解为可以在较少的传递中排序的块
使用并行插入+并行选择可能会更快,但可能没有必要。如果没有插入和“alter session enable parallel dml”
,请不要进行并行选择