2017-04-22 96 views
0

我有一个包含3亿条记录的表(表A),我想根据某些条件执行数据保留活动。所以我想删除大约200M表中的记录。根据条件从非常大的表中删除旧记录

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

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

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

我想知道的是,

  • 有没有更好的办法从表-A提取和将其加载表-B。
  • 除了创建一个临时表(Table-B)之外,还有其他更好的方法吗?

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

谢谢。

+3

这两个表都在同一个数据库中吗?如果是的话,您是否使用SQL Loader来加载乳清?你不能只是'插入tableB select * from tableA'吗?另外创建tableB作为'no logging'来获得更快的插入。 Google'nologging'获取更多细节。 – Utsav

+0

我同意@Utsav,只是'插入/ * +追加* /到t2选择*从t1哪里'应该需要几分钟而不是几个小时。这是我会更担心的'删除'。您是否有下一次需要分区的选项? –

+0

关于“除了创建临时表(Table-B)之外是否还有其他更好的方法”,我不明白你的过程逻辑。表B是什么?我的意思是,创建它的替代方法不会创建它。 –

回答

1

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

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

-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个交易移动你的记录。你可以使用集合和批量插入来优化它,但我想保留简单的代码。

+0

-1这不是一个好建议。这将把负载的持续时间从5小时扩大到更多的小时。正如其他人已经说过的:拳头考虑是否真的有必要使用表B,其次如果有必要,那么使用'插入追加',也许nologging。你的方法没有考虑到这一点,但增加了删除数据的时间。 append-hint对插入值语句没有影响,并且不断在pl/sql和sql上下文之间切换会使这种方法更加缓慢。 – miracle173

+0

再加上'insert * values'语句的'/ * + append_values * /',并且只在11.2中添加,而OP仍然在10g上。在那个循环中好像有一个'commit'。 –

0

使用ROWID最好的使用,但内联光标可以帮助ü更 插入到表中的值(SELECT * FROM表B,其中=标准),然后截断表一

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

  • 表-B。有没有更好的方法,而不是创建一个临时表
    表(表B)?更好的办法是表的分区一个

0

按照您的标准对表格进行分区可能是一个选项。

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

然后,当需要删除所有旧的一月份数据时,您只需删除该分区即可。