SQL Delete *导致性能问题

时间:2017-12-01 11:14:31

标签: sql oracle

我有一个PL / SQL文件,一次需要删除整个表。挑战是:

  1. 截断表 无法使用,因为无法为相关数据库用户提供执行DDL命令的权限(由于SOX合规性)

    < / LI>
  2. delete * 在表格记录数量较少的情况下效果很好。但是,该表可能有数百万条记录,在这种情况下,重做日志文件大小会急剧增加,从而导致性能问题

  3. 以下解决方案工作:

    1. 增加重做日志文件大小
    2. 以批处理方式删除记录(在嵌套事务中)
    3. 有没有更好更有效的方法来解决这个问题?

4 个答案:

答案 0 :(得分:2)

如果重做日志文件大小有问题,您可以在每次删除后删除部分COMMIT。例如:

LOOP 
  --delete 1000000 records in each iteration
  DELETE FROM tmp_test_table 
  WHERE 1=1--:WHERE_CONDITION
  AND   rownum <= 1000000;
  -- exit when there is no more to delete
  EXIT WHEN SQL%rowcount = 0;
  COMMIT; 
END LOOP;

答案 1 :(得分:0)

您可以使用以下几种方法: 使用分区:执行批量删除的最快方法是删除Oracle分区。 调整delete子查询:许多Oracle删除使用where子句子查询,优化子查询将提高SQL删除速度。 使用批量删除:Oracle PL / SQL具有批量删除操作符,通常比标准SQL删除更快。 丢弃指数&amp;约束:如果要在夜间批处理作业中调整删除,请考虑删除索引并在删除作业完成后重建它们。 Small pctused:对于调整批量删除,您可以通过将Oracle设置为仅在块为空时通过为pctused设置较低值来将块重新添加到空闲列表来减少空闲列表开销。 并行化删除作业:您可以与并行提示并行运行大量删除。如果您有36个处理器,则全扫描速度可以快35倍(cpu_count-1) 考虑NOARCHIVELOG:首先进行完全备份,然后将数据库退回到NOLOGGING模式以进行删除,然后在ARCHIVELOG模式后再次将其退回。 使用CTAS:您可以尝试的另一个选项是使用CTAS创建新表,其中select语句过滤掉要删除的行。然后重命名原始文件,然后重命名新表并传输约束和索引。 最后,抵制做“软”删除的诱惑,一种可能致命的脑死亡方法。

答案 2 :(得分:0)

这种方法有优势。 您可以在所需的表空间中创建一个表,而不会在磁盘所需的分区上出现碎片。 表的物理重新创建将删除表的碎片并删除链接的行。

如果您需要从表格中删除60-99%的行。 emp 然后你需要制作一个新表emp_new

create table emp_new ;

将所需行复制到新表

insert into emp_new select * from emp where date_insert> sysdate-30

在新表上创建索引

create index PK_EMP on emp_new.

删除旧的emp表

drop table emp.

将新表重命名为旧名称。

rename table emp_new to emp

答案 3 :(得分:-2)

在Oracle PL / SQL中,DDL语句应该在语句之前使用Execute Immediate。因此你应该使用:

autocmd InsertLeave <buffer> execute "normal! giXXX\<Esc>"

除了你还可以使用

execute immediate 'truncate table schema.tablename';

尝试在您的案例中可能有效的任何人