哪种delete语句更适合删除数百万行

时间:2019-06-07 06:57:53

标签: sql oracle sql-delete large-data

我有一个包含数百万行的表。 我想根据last_updated列的值删除超过一周的所有数据。

这是我的两个查询,

方法1:

Delete from A where to_date(last_updated,''yyyy-mm-dd'')< sysdate-7;

方法2:

l_lastupdated varchar2(255) := to_char(sysdate-nvl(p_days,7),'YYYY-MM-DD');
insert into B(ID) select ID from A where LASTUPDATED < l_lastupdated;
delete from A where id in (select id from B);

考虑性能,安全性和锁定性的哪个更好?

3 个答案:

答案 0 :(得分:1)

您存储的日期格式似乎适合进行正确的排序,因此您可以反过来将sysdate转换为字符串:

--this is false today    
select * from dual where '2019-06-05' < to_char(sysdate-7, 'YYYY-MM-DD'); 

--this is true today
select * from dual where '2019-05-05' < to_char(sysdate-7, 'YYYY-MM-DD'); 

因此它将是:

Delete from A where last_updated < to_char(sysdate-7, ''yyyy-mm-dd'');

具有使用默认索引(如果有)的好处。

它的缺点是依赖于可能会更改的String / Varchar顺序,即北NLS发生了更改(如果我没记错的话),因此在任何情况下,您都应该在...之前进行一些测试...

从长远来看,您应该强制将列更改为适当的日期数据类型,但我想这对您不正确的了解;)

答案 1 :(得分:0)

如果您要删除表中的大多数行,我建议您采用另一种方法,即:

create <new table name> as
select *
from   <old table name>
where  <predicates for the data you want to keep>;

然后

drop table <old table name>;

最后,您可以将新表重命名为旧表。

您始终可以对新表进行分区(即,使用包含分区子句的单独语句创建新表,然后从旧表中插入一个作为选择插入新表中的内容)。

这样,当您需要删除行时,只需删除相关分区即可。

答案 2 :(得分:0)

假设删除操作删除了很大一部分数据和数百万行,请采用以下三种方法:

create table tmp
  Delete from A where to_date(last_updated,''yyyy-mm-dd'')< sysdate-7;

drop table a;

rename tmp to a;

https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:2345591157689

很显然,您需要复制所有索引,授权等。但是在线重新定义可以帮助完成此https://oracle-base.com/articles/11g/online-table-redefinition-enhancements-11gr1

到达12.2时,还有另一个更简单的选择:过滤后的举动。

这是一个alter table移动操作,带有一个额外的子句,指出要保留的行:

create table t (
  c1 int
);

insert into t values ( 1 );
insert into t values ( 2 );
commit;

alter table t
  move including rows where c1 > 1;

select * from t;

C1   
    2 

当您等待升级到12.2+时,如果由于某种原因不想使用create-as-select方法,则方法1更好:

  • 这两种方法都从A * =>删除相同的行,完成删除的工作量相同
  • 选项1有一个陈述;选项2有两个陈述; 2> 1 =>选项2的工作量更多

*语句级别的一致性意味着您在运行流程时可能会得到不同的结果。假设另一个会话尝试更新您的流程将要删除的旧行。

仅删除,更新将被阻止,直到删除完成。此时行已消失,因此更新不执行任何操作。

如果您先执行插入操作,则另一个会话可以在插入操作完成之前更新并提交该行。因此更新“成功”。但是删除后将其删除!可能导致一些不满意的客户...