DELETE edms_personalisation
WHERE mail_id NOT IN (SELECT mail_id
FROM edms_mail)
AND rownum <= 25000;
您好,上面的SQL(从SQLPLUS接口运行)能否以更有效的方式编写?
最近我注意到edms_personalisation表有大约80万行,而edms_mail表有大约120,000行。
我想创建一个清除脚本,每次运行只影响有限数量的行,这样我就可以将它粘贴在Cron作业上并让它每5分钟运行一次。
欢迎任何想法。
(注意:适当的索引在数据库表上执行EXIST)
答案 0 :(得分:4)
DELETE edms_personalisation p
WHERE NOT EXISTS (SELECT 'X'
FROM edms_mail m
WHERE m.mail_id = p.mail_id)
AND rownum <= 25000;
或
DELETE edms_personalisation
WHERE mail_id IN (SELECT mail_id FROM edms_personalisation
MINUS
SELECT mail_id FROM edms_mail)
AND rownum <= 25000;
如果Oracle我会编写一个PL/SQL
来批量收集要删除的所有符合条件的邮件ID。并直接查询索引(批量绑定)。你也可以批量生产。
否则,由于'要删除'表太大,更好的方法是将好数据复制到临时表中,截断表,然后从temp重新加载。当必须在频繁的循环中完成时,必须使用上述方法!
试试这个!祝你好运!
答案 1 :(得分:1)
我认为问题中的删除声明会正常工作。 问题是删除的重做日志量是多少 声明生成。
一般的经验法则是用a批量删除行 虽然批量大小没有突然出现在线重做,但仍然在其中提交 日志文件。 [我想这个问题与ORACLE有关]
如果删除是一次时间活动,但您每次都这样做 5分钟,批量25000,以应对行数 要删除然后将所需的行复制到新表, 截断实际表并将数据从新表传输到实际表 表。当然每五分钟做一次是没有意义的 据我说。
如果要删除的数据对于第一次运行而言将是巨大的,而对于后续运行则不会 然后我会建议按照第二轮中提到的方法进行第一次运行 以及后续运行的第1点中提到的方法。
免责声明:我认为其他人会面临同样的问题,并会用上面提到的更好的解决方案来解决它。
答案 2 :(得分:0)
您可以SET ROWCONT N
将受下一批影响的行限制为N
。例如
SET ROWCOUNT 10
GO
DELETE edms_personalisation
WHERE mail_id NOT IN (SELECT mail_id FROM edms_mail)
AND ROWNUM <= 25000;
GO
将删除不超过10行。
否则,我会考虑使用批量复制(或bcp)将数据复制到新表,跳过您计划删除的行。供参考:
out/queryout
不会阻止来源
表,但in
将阻止目标表。