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

Oracle如何从表中删除除少数分区以外的数据,oracle,partition,Oracle,Partition,我有一个很大的表,其中有很多数据被划分成多个分区。我想保留一些分区,但从表中删除其余的数据。我试图搜索一个类似的问题,但在stackoverflow中找不到。在Oracle中编写查询以实现相同目的的最佳方法是什么 从特定分区删除数据很容易:此语句清除2012年2月的所有数据: delete from t23 partition (feb2012); 更快的方法是截断分区: alter table t23 truncate partition feb2012; alter table t23

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

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

delete from t23 partition (feb2012);
更快的方法是截断分区:

alter table t23 truncate partition feb2012;
alter table t23 drop partition feb2012;
这里有两个潜在的障碍:

  • 如果外键引用表,Oracle不会让我们截断分区
  • 该操作使任何分区索引无效,因此我们需要在以后重新生成它们
  • 而且,它是DDL,所以没有回滚

    如果我们再也不想存储当月的数据,我们可以删除分区:

    alter table t23 truncate partition feb2012;
    
    alter table t23 drop partition feb2012;
    
    当我们想要破坏多个分区并且我们不喜欢所有的类型时,问题就出现了。我们不能参数化分区名,因为它是一个对象名而不是变量(没有引号)。所以只留下动态SQL

    因为您希望删除大部分数据,但保留分区结构,所以截断分区是最好的选择。请记住使任何完整性约束无效(并在之后恢复它们)

    您肯定应该首先使用注释掉的
    executeimmediate
    call运行循环,这样您就可以看到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复制回数据 表到原始表。”


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

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

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

    ALTER TABLE table_name DROP PARTITION partition_name UPDATE GLOBAL INDEXES;
    

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

    是否删除记录但保留分区?或者也删除分区?不,我只想删除记录,但保留分区本身-谢谢你的回复。我需要保留几个分区中的数据,并从表中删除其余的数据。您是否建议检查表的所有分区,并从除我需要的分区之外的所有分区中删除?从分区删除与alter table truncate partition有何不同?除了
    delete
    DROP
    之外,您还可以
    truncate
    分区。@BolimeraHannah-对不起,我还没有完全处理zap与retain的比率。我已经根据您的要求修改了我的答案。或者,我不想在所有分区上循环并删除它们并保留我需要的分区,而是考虑将我需要的分区数据复制到临时表中,截断原始表,并将数据从临时表复制回原始表。不确定哪种方法在性能方面更好。您好,如果您删除分区,您可以使用子句
    更新全局索引
    。使用此子句,您不会使索引无效!