根据条件从非常大的表中删除旧记录

时间:2017-04-22 09:49:03

标签: database oracle plsql oracle10g sql-loader

我有一个包含3亿条记录的表(表A),我想根据某些标准进行数据保留活动。所以我想删除该表的大约200M记录。

关于性能,我计划使用Table-A中最早的10M记录创建一个新表(表B)。然后我可以从Table-B中选择符合条件的记录,并在表A中删除它。

从表A中提取10M记录并使用SQL Loader加载到表B中需要大约5个小时。

我已经创建了索引,并且在适用的地方使用了parallel 32。

我想知道的是,

  • 有没有更好的方法从Table-A中提取并在Table-B中加载它。
  • 除了创建临时表(表-B)之外,还有更好的方法。

DBMS:Oracle 10g,PL / SQL和Shell。

感谢。

6 个答案:

答案 0 :(得分:2)

如果要删除表中70%的记录,最好的方法是创建一个包含剩余30%行的新表,删除旧表并将新表重命名为旧桌子。创建新表的一种可能性是create-table-as-select语句(CTAS),但是也有可能使对运行系统的影响小得多,例如:可以使用物化视图来选择剩余数据并将物化视图转换为表格。该方法的细节取决于要求。 这种读取和写入比删除旧表的行更有效。

如果删除旧表的行,则可能需要重新组织旧表,这也将最终写入剩余的30%的数据。

答案 1 :(得分:0)

最好使用rowid但内联游标可以帮助你 在表中插入一个值(从表B中选择*,其中=条件)然后截断表A

答案 2 :(得分:0)

  • 有没有更好的方法从Table-A中提取并加载它?您可以使用并行CTAS - 创建table-b作为select-table-a。您可以一步使用压缩和并行查询。

  • 表-B。有没有更好的方法,除了创建临时
    表(表-B)?更好的方法是分区表

答案 3 :(得分:0)

根据您的标准对表格进行分区可能是一种选择。

考虑一个标准是月份的情况。所有1月份的数据都属于Jan分区。所有2月份的数据都属于2月份的分区...

然后,当需要删除所有旧的1月数据时,您只需删除分区。

答案 4 :(得分:0)

我在搜索条件中使用的列上缺少一个索引。 除此之外,引用表上也缺少一些索引。

  

除了这个@miracle173答案也不错,但我们也有一些外键,如果我们使用这种方法可能会产生问题。

+1 to @miracle173

答案 5 :(得分:-1)

可能更好的方法是分区表A,但如果没有,你可以尝试快速和简单:

declare
    i pls_integer :=0 ;
begin
    for r in
    (   -- select what you want to move to second table
        SELECT  
            rowid as rid,
            col1,
            col2,
            col3
        FROM
            table_a t
        WHERE
            t.col < SYSDATE - 30 --- or other criteria 
    )
    loop
        insert /*+ append */ into table_b values (r.col1, r.col2, r.col3 ); -- insert it to second table
        delete from table_a where rowid = r.rid; -- and delete it
        if i < 500 -- check your best commit interval
        then
            i:=i+1;
        else
            commit;
            i:=0;
        end if;    
    end loop;
    commit;
end;

在上面的示例中,您将在小型500行交易中移动记录。你可以使用集合和批量插入来优化它,但我想保留简单的代码。