【问题标题】:Oracle how to delete from a table except few partitions dataOracle如何从表中删除除少数分区数据
【发布时间】:2014-12-30 22:07:44
【问题描述】:

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

【问题讨论】:

  • 您要删除记录但保留分区吗?或者也删除分区?
  • 不,我只想删除记录但保留分区本身 - 谢谢

标签: oracle partition


【解决方案1】:

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

delete from t23 partition (feb2012);

更快的方法是截断分区:

alter table t23 truncate partition feb2012;

这里有两个潜在的障碍:

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

另外,它是 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 复制回数据 表到原表。 "

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

【讨论】:

  • 感谢您的回复。我的需要是保留几个分区中的数据并从表中删除其余数据。您是否建议检查表的所有分区并从除我需要的分区之外的所有分区中删除?从分区中删除与更改表截断分区有何不同?
  • 除了DELETEDROP 你也可以TRUNCATE 分区。
  • @BolimeraHannah - 抱歉,我没有完全处理 zap 保留的比例。我已根据您的要求修改了答案。
  • 或者,我不是循环遍历所有分区并删除它们并保留我需要的分区,而是考虑将我需要的分区的数据复制到临时表中并截断原始表并复制回从临时表到原始表的数据。不确定哪种方法在性能方面更好。
  • 您好,如果您删除分区,您可以使用子句update global indexes。使用此子句,您不会使索引无效!
【解决方案2】:

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

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

ALTER TABLE table_name DROP PARTITION partition_name UPDATE GLOBAL INDEXES;

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-13
    • 1970-01-01
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-18
    • 1970-01-01
    相关资源
    最近更新 更多