1

目前我正在使用以下语句:

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

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

谢谢

4

4 回答 4

3

首先,这肯定是一张大桌子。否则,我认为像您这样需要很长时间的声明毫无意义。

那么有两种可能:

1)delete语句影响很多很多记录。

那么声明需要很长时间是很自然的。必须扫描整个表(全表扫描)。您只能通过并行化语句来加快速度:

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

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

那么 Oracle 最好使用索引。由于您只要求时间戳列的日期部分,因此您将创建一个函数索引:

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

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

于 2013-09-25T10:42:55.440 回答
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');
于 2013-09-25T09:56:57.790 回答
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) 上没有函数索引,在这种情况下应该提供更好的性能。

根据我以前的经验,(没有直接的事实或理论支持,甚至更多,事实与这种方法相反):你可以把它分成更小的部分

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 隔离级别。

于 2013-09-25T09:10:39.183 回答
0

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

从 tbl_name 中删除,其中tbl_name.IDLOWER_ID_VALUEUPPER_ID_VALUE之间

注意: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 命令时,已删除的行存储在回滚段中,因此,如果需要,可以撤消更改。因此,回滚中的行的图像当前不存在于表中。现在所有的回滚块也被写入重做日志文件。所以你有带有表的数据块(当然没有删除的行)和带有旧图像的回滚块都产生重做,这占了额外的存档日志。

因此,最好一步完成,而不是将其分解为多个事务并执行。

于 2013-09-25T09:28:51.143 回答