我将在每个批处理中删除数百万行,由于行太多,我无法将它们一起删除。我想删除行没有日志,但我没有找到任何东西。有人可以帮我写一个删除无日志查询吗?
我的查询是这样的:
DELETE
FROM MyTable
WHERE TO_CHAR(MyDate, 'YYYYMM') = 202101
即使我只考虑一个月(大约600万条记录),我也无法删除它们
删除操作总是logging
,并且还需要大量的undo
,这就是为什么当涉及大量行时,它们在性能方面可能会很昂贵。此外,如果您有索引,那么也必须删除那里的行。
有几个选项,但它们很大程度上取决于您的环境。我会尝试两种方法
我使用并行度8。如果您的数据库服务器的CPU较少或较多,则可以使用度数。我不会在删除中使用太多的程度,但我会在选项2
中尽可能地使用选项1
alter session enable parallel dml ;
delete /*+parallel(a,8) */ from myTable a where TO_CHAR(MyDate, 'YYYYMM') = 202101 ;
commit;
选项2(使用CTAS和截断/插入)
alter session enable parallel dml;
alter session enable parallel ddl;
create table MyBkpTable parallel compress nologging pctfree 0
as select /*+parallel(a,8) */ * from MyTable a
where TO_CHAR(MyDate, 'YYYYMM') != 202101 ;
truncate table MyTable reuse storage ;
insert /*+append parallel(a,8) */ into MyTable a
select /*+parallel(b,8) */ * from MyBkpTable b;
commit;
如果表上有很多索引,将所有索引标记为不可用,并在运行插入追加之前使用alter session set skip_unusable_indexes=true
。最后,重建所有索引。
当表被分区时,为了从partition pruning
中获益,您可以使用(,只要分区键是MyDate)
delete /*+parallel(a,8) */ from myTable a where MyDate >= date '2021-01-01' and MyDate < date '2021-02-01' ;
或者更好,直接截断所有的分区
alter table myTable truncate partition <<partition_name>>