删除具有20m记录的表上Date = DD.MM.YYYY的位置

时间:2013-09-25 08:56:23

标签: sql oracle oracle11g

目前我正在使用声明:

delete
from tbl_name
where trunc(tbl_name.Timestamp) = to_date('06.09.2013','DD/MM/YYYY');

但这需要很长时间。 有没有办法加快速度?

谢谢

4 个答案:

答案 0 :(得分:3)

首先,这肯定是一张大桌子。否则,我认为像你这样的陈述没有意义。

然后有两种可能性:

1)删除语句影响许多记录。

然后说这句话很自然。必须扫描整个表格(全表扫描)。你只能通过并行化语句来加快速度:

delete /*+parallel(tbl_name,4)*/ from tbl_name ...

2)delete语句影响表中相当小比例的记录。

然后,Oracle建议使用索引。由于您只询问时间戳列的日期部分,因此您将创建一个函数索引:

create index index_name on tbl_name( trunc(the_timestamp) );

一旦表上有可用的索引,Oracle就可以使用它根据trunc(the_timestamp)查找有关选择,更新和删除的所需记录。

答案 1 :(得分:1)

在右侧使用介于值之间而不是在左侧使用trunc。

delete from tbl_name
where tbl_name.Timestamp between to_date('06.09.2013 00:00:00','DD/MM/YYYY hh24:mi:ss')
and  to_date('06.09.2013 23:59:59','DD/MM/YYYY hh24:mi:ss');

答案 2 :(得分:0)

您可以使用更好的条件而不是trunc,尤其是如果您在tbl_name.Timestamp字段上有索引:

    tbl_name.Timestamp >= to_date('06.09.2013','DD/MM/YYYY') --inclusive
AND tbl_name.Timestamp <  to_date('07.09.2013','DD/MM/YYYY') --exclusive

我假设你没有trunc(tbl_name.Timestamp)上的函数索引,在这种情况下应该提供更好的性能。

<子> 根据我以前的经验,(没有直接的事实或理论支持,甚至更多,the facts are against this approach):你可以把它分成更小的一串

delete
from tbl_name
where 
  id in (select id from tbl_name 
  and trunc(tbl_name.Timestamp) = to_date('06.09.2013','DD/MM/YYYY') 
  and rownum<10000); -- tune this to your liking

重复一遍。不要忘记介于两者之间......这对我有帮助,我们使用的是SNAPSHOT隔离级别。

答案 3 :(得分:0)

我在想,既然您指的是tbl_name.Timestamp列,那么我确信必须有一个与之关联的主键。如果主键是数字值,您可以在delete语句中使用该索引,类似于:

  

LOWER_ID_VALUE UPPER_ID_VALUE

之间的 tbl_name.ID 中的tbl_name删除

注意:LOWER_ID_VALUE和UPPER_ID_VALUE本质上是包含性的,这意味着这两个ID的记录也将被删除。

ppeterka 66使用rownum分解删除的想法是不可行的。看看http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:2345591157689

  

假设您正在运行Oracle,当发出DELETE命令时,已删除的行将存储在回滚段中,因此,如果需要,可以撤消更改。因此,回滚中的行的图像当前不存在于表中。现在所有的回滚块也被写入重做日志文件。所以你有表的数据块(当然没有删除的行)和旧图像的回滚块都产生重做,这会占用额外的存档日志。

因此,最好一步到位,而不是将其分解为多个交易并进行。