sql—我想删除oracle中的大量数据

r6l8ljro  于 2021-08-09  发布在  Java
关注(0)|答案(2)|浏览(297)

我使用了此代码,但时间太长,计算机崩溃:

begin
  for i In 0..1000
  loop
    delete from mytable WHERE user_date BETWEEN to_char(to_date('20120101000000','YYYYMMDD')+i,'YYYYMMDDHH24MISS') and to_char(to_date('20120101235959','YYYYMMDD')+i,'YYYYMMDDHH24MISS');
  end loop;
end;

我想我需要对这段代码应用bulksql。
我必须删除2年范围内的数据
请帮帮我。
用户日期类型为char(20101000000)

8hhllhi2

8hhllhi21#

72.000.000排是很多,所以需要采取特别措施。我会计算有多少行会被删除,有多少行会保留在f.i.:

SELECT todo, count(*) FROM (
  SELECT CASE 
           WHEN user_date BETWEEN '20120101000000' AND '20150101000000' 
           THEN 'delete'
           ELSE 'keep'
         END AS todo
    FROM mytab
) GROUP by todo;

正如@littlefoot所说,如果要删除足够多的内容,我会尝试CTA方法:

CREATE TABLE mytemp NOLOGGING AS
SELECT * FROM mytable 
 WHERE user_date NOT BETWEEN '20120101000000' AND '20150101000000';

DROP TABLE mytable;
RENAME mytemp TO mytable;

注意:您必须重新创建所有索引、特权等。请在测试系统上尝试,最好是在一个小示例上。
另一方面,如果只删除一小部分行,而保留其余的行,我将遵循@tim biegeleisen的方法:

CREATE INDEX i ON mytable(user_date);

DELETE FROM mytable
 WHERE user_date BETWEEN '20120101000000' AND '20150101000000';

如果采用第二种方法,并且行数仍然很大,则可能需要通过重新组织表来释放空间。询问dba。
如果您没有测试系统,可以通过复制大表的一个小样本(例如0.1%)来创建:

CREATE TABLE mytest NOLOGGING AS SELECT * FROM mytable (SAMPLE 0.1);

我不完全理解您的日期逻辑,因此在我的示例中使用了从2012年1月1日到2014年12月31日的所有日期。
哦,是的,一匹没有名字的马是完全正确的,永远不要把日期储存在varchar里。

kq4fsx7k

kq4fsx7k2#

您使用的是哪个版本的oracle?如果是19c,你能做什么

alter table mytable move including rows where user_date NOT BETWEEN '20120101000000' AND '20150101000000' online.

相关问题