2

我正在使用提到的查询从我的表中删除 2.5 亿多行,这需要更多时间

我已尝试使用 t_delete 限制,最高为 20000。

仍然缓慢的删除发生。

请在同一代码中提出一些优化建议,以更快地完成我的工作。

DECLARE
TYPE tt_delete IS TABLE OF ROWID; t_delete tt_delete;
CURSOR cIMAV IS SELECT ROWID FROM moc_attribute_value where id in (select 
id from ORPHANS_MAV);

total Number:=0;
rcount Number:=0;
Stmt1 varchar2(2000);
Stmt2 varchar2(2000);
BEGIN
---    CREATE TABLE orphansInconsistenDelProgress (currentTable 
VARCHAR(100), deletedCount INT, totalToDelete INT);
---    INSERT INTO orphansInconsistenDelProgress (currentTable, 
deletedCount,totalToDelete) values ('',0,0);
Stmt1:='ALTER SESSION SET parallel_degree_policy = AUTO';
Stmt2:='ALTER SESSION FORCE PARALLEL DML';
EXECUTE IMMEDIATE Stmt1;
EXECUTE IMMEDIATE Stmt2;
---   ALTER SESSION SET parallel_degree_policy = AUTO;
---   ALTER SESSION FORCE PARALLEL DML;
COMMIT;

--- MOC_ATTRIBUTE_VALUE

SELECT count(*) INTO total FROM ORPHANS_MAV;
UPDATE orphansInconsistenDelProgress SET currentTable='ORPHANS_MAV', 
totalToDelete=total;
rcount := 0;
OPEN cIMAV;
LOOP
    FETCH cIMAV BULK COLLECT INTO t_delete LIMIT 2000;
            EXIT WHEN t_delete.COUNT = 0;
            FORALL i IN 1..t_delete.COUNT
        DELETE moc_attribute_value WHERE ROWID = t_delete (i);
    COMMIT;
    rcount := rcount + 2000;
    UPDATE orphansInconsistenDelProgress SET deletedCount=rcount;
END LOOP;
CLOSE cIMAV;
COMMIT;
END;
/ 
4

3 回答 3

1

单个 Oracle 并行查询可以简化代码并提高性能。

declare
    execute immediate 'alter session enable parallel dml';

    delete /*+ parallel */
    from moc_attribute_value
    where id in (select id from ORPHANS_MAV);

    update OrphansInconsistenDelProgress
    set currentTable = 'ORPHANS_MAV', 
    totalToDelete = sql%rowcount;

    commit;
end;
/

一般来说,我们希望要么让 Oracle 将任务分解成小块,要么使用我们自己的自定义分块。原始代码似乎同时进行了这两项工作——它以块的形式读取数据,然后提交每个块以进一步划分为并行删除。这种方法会产生很多小块,Oracle 可能会在线程协调等事情上浪费大量时间。

删除大量行的成本很高,因为无法避免 REDO 和 UNDO。您可能想要研究使用 DDL 选项,例如截断分区,或删除并重新创建表。(但是要小心重新创建对象,很难完美地重新创建复杂的对象。我们往往会忘记特权和表选项之类的东西。)

调整并行性和大型作业很复杂。使用最好的监控工具很重要,以确保 Oracle 请求、分配和使用正确数量的并行进程,并且执行计划是正确的。使用单个 SQL 语句的一大优势是您可以使用实时 SQL 监控报告来监控进度。如果您拥有 Diagnostics 和 Tuning Pack 许可证,请SQL_ID在 中找到GV$SQL并生成报告select dbms_sqltune.report_sql_monitor('your SQL_ID here');

于 2019-07-07T17:59:10.163 回答
0

如果您只保留一小部分行,则复制要保留的行,然后交换表并删除旧表可能会快得多。

(不,我不知道这比删除更快的阈值。)

于 2019-08-17T21:26:35.753 回答
0

也许使用 SQL TRUNCATE TABLE,

Truncate table 比 DELETE TABLE 命令更快并且使用更少的资源。

于 2019-07-07T09:09:15.023 回答