建议一种从oracle中的巨大表中删除小数据的方法

问题描述:

我有一个拥有3亿行数的表。我需要从中删除约300万。我在这张桌子上没有任何索引。数据将根据特定的日期列删除。像建议一种从oracle中的巨大表中删除小数据的方法

delete from table where column_name = '1-dec-2010' 

什么是最好的解决方案来执行此操作?

  1. 索引列并执行删除。
  2. 保持表,因为它是即删除不使用索引

使用索引将使用索引扫描+更新索引中删除后的开销。没有索引将使用全表扫描。那么是否有任何门槛说X百万行索引比全表扫描更受欢迎?

+0

这是一次性的,还是正常的工作? – 2015-08-20 12:59:42

您有以下选项(在效率的顺序排列):

  1. 分区。 Enterprise Edition的额外费用选项。如果数据按天分区,那么删除给定日期的数据就像删除当天的分区一样简单。快速,高效,美观但昂贵(除非客户可以获得很好的折扣)。

  2. 创建一个新表并将要保留的数据复制到新表中(使用直接路径插入)。放下旧桌子;重命名新表(或使用动态管理的同义词)。在这种情况下,索引可能是有用的,但是由于选择性不好,Oracle可能会忽略这种情况(只有大约1%的数据会被访问;优化程序可能认为这不值得处理索引)。 有关此选项,请参阅Tom Kyte's comments

  3. 使用指数。这肯定会加速查找需要删除的记录,但删除操作仍然会非常缓慢(重做和全部)。

+0

嗨巴拉尼,谢谢你的回答。由于这是现有的表格,我们不会通过对其进行分区来改变结构。根据第二种选择,我们在100M桌面上尝试了它,但令人费解的是它比使用索引的简单删除慢。我甚至测试过从180M记录中删除3M,并且索引删除比非索引删除快。但我不确定数据超过300M时会不会发生同样的情况。 – 2012-02-13 09:36:54

那么,你是否删除了固定的1%的数据?如果是这样,并且不考虑分区,请执行以下操作:

  1. 在日期列上创建索引。
  2. 确保为该索引和表收集优化程序统计信息。

运行查询类似如下:

select di.table_name, di.index_name, di.leaf_blocks, 
     di.clustering_factor, dt.blocks 
    from all_indexes di 
     left join all_tables dt 
     on di.table_owner = dt.owner 
     and di.table_name = dt.table_name 
where di.index_name = 'my_new_index' 
  • LEAF_BLOCKS给你 指数 “数据块” 的粗略尺寸。
  • CLUSTERING_FACTOR告诉你需要多少个表I/O来 通过该索引读取整个表。
  • BLOCKS给你 块的表的大小。

如果CLUSTERING_FACTOR是非常接近的BLOCKS的大小,则该表是更多或更少的存储在索引中的顺序。

所以,如果你删除表的1%,看哪个更小:

BLOCKS,或((LEAF_BLOCKS + CLUSTERING_FACTOR)/100)

if块是显著更大的 - 可能是10倍大的量级 - 比计算表达式,那么索引可能会加快删除。