目前我正在使用以下语句:
delete
from tbl_name
where trunc(tbl_name.Timestamp) = to_date('06.09.2013','DD/MM/YYYY');
但这需要非常非常长的时间。有没有办法加快速度?
谢谢
首先,这肯定是一张大桌子。否则,我认为像您这样需要很长时间的声明毫无意义。
那么有两种可能:
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) 查找有关选择、更新和删除的所需记录。
在右侧使用中间值,而不是在左侧使用 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');
您可以使用更好的条件来代替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 隔离级别。
我在想,既然您指的是该tbl_name.Timestamp
列,那么我确信必须有一个主键也与之关联。如果主键是数值,您可以在删除语句中使用该索引,类似于:
从 tbl_name 中删除,其中tbl_name.ID在LOWER_ID_VALUE和UPPER_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 命令时,已删除的行存储在回滚段中,因此,如果需要,可以撤消更改。因此,回滚中的行的图像当前不存在于表中。现在所有的回滚块也被写入重做日志文件。所以你有带有表的数据块(当然没有删除的行)和带有旧图像的回滚块都产生重做,这占了额外的存档日志。
因此,最好一步完成,而不是将其分解为多个事务并执行。