Oracle如何从表中删除少数分区数据

时间:2014-11-04 04:57:21

标签: oracle partition

我有一个大表,其中大量数据被分区为多个分区。我想保留一些分区,但删除表中的其余数据。我尝试搜索类似的问题,但无法在stackoverflow中找到它。在Oracle中编写查询以实现相同的最佳方法是什么?

2 个答案:

答案 0 :(得分:3)

从特定分区中删除数据很容易:此语句将清除2012年2月的所有数据:

delete from t23 partition (feb2012);

更快的方法是截断分区:

alter table t23 truncate partition feb2012;

这里有两个潜在的障碍:

  1. 如果我们有引用该表的外键,Oracle不会让我们截断分区。
  2. 该操作使任何已分区的索引无效,因此我们需要在之后重建它们。
  3. 此外,它是DDL,所以没有回滚。

    如果我们再也不想存储该月的数据,我们可以放弃分区:

    alter table t23 drop partition feb2012;
    

    当我们想要删除多个分区并且我们不喜欢所有打字时,问题就出现了。我们无法对分区名称进行参数化,因为它的对象名称不是变量(没有引号)。所以只留下动态SQL。

    由于您要删除大部分数据但保留分区结构,因此截断分区是最佳选择。请记住使任何完整性约束无效(并在之后恢复它们)。

    declare
        stmt varchar2(32767);
    begin
        for lrec in ( select partition_name
                      from user_tab_partitions
                      where table_name = 'T23'
                      and partition_name like '%2012'
                    )
        loop
            stmt := 'alter table t23 truncate partition '
                        || lrec.partition_name
                      ;
            dbms_output.put_line(stmt);
            execute immediate stmt;
        end loop;
    end;
    /
    

    您应该首先运行循环,并将execute immediate调用注释掉,这样您就可以看到WHERE子句正在选择哪些分区。显然,你有一个备份,可以恢复你并不意味着删除的数据。但进行恢复的最快方法不需要恢复。

    然后运行此查询以查看应重建的分区:

    select ip.index_name, ip.partition_name, ip.status 
    from user_indexes i
         join user_ind_partitions ip
          on  ip.index_name = i.index_name
    where i.table_name = 'T23'
    and ip.status = 'UNUSABLE';
    

    您可以以类似的方式自动执行重建语句。


      

    "我正在考虑将我需要的分区数据复制到temp中   表并截断原始表并从temp中复制数据   表到原始表。 "

    这是另一种做事方式。使用交换分区可能会非常快。它可能也会慢一点。它还取决于外键和索引之类的东西,以及zapped分区与保留分区的比率。如果性能很重要和/或您需要定期进行此操作,那么您应该对各种选项进行基准测试,看看什么最适合您。

答案 1 :(得分:0)

从分区表删除分区时必须非常小心。分区表通常用于大数据表,并且当(且仅当)在表上具有全局索引时,使用drop partition使您的全局索引无效,而您应该在大表中重建全局索引,这是灾难。

在这种情况下,为了最小化表查询的副作用,我首先删除分区中的记录并将其设置为空分区,然后使用

ALTER TABLE table_name DROP PARTITION partition_name UPDATE GLOBAL INDEXES;

删除空分区而不会使我的全局索引无效。