我尝试在邮件列中删除具有空值的行,当且仅当存在具有相同person_id的非空值的行时。
DELETE
FROM
EMP_MAIL EM
WHERE
MAIL IS NULL
AND EXISTS
(
SELECT
EMP_ID
FROM
EMP_MAIL EM2
WHERE
MAIL IS NOT NULL
AND EM.EMP_ID = EM2.EMP_ID
) ;
但需要很长时间。 (我在EMP_MAIL(EMP_ID)上有一个非唯一索引)
是否有更好的方法来执行此操作?
答案 0 :(得分:0)
这取决于您的输入数据,我希望此查询可以帮助您或为您提供一些解决问题的线索:
DELETE
from
EMP_MAIL t1
where
t1.MAIL is null and
not Exists
(select t2.EMP_ID from (select EMP_ID from EMP_MAIL where mail is not null
minus
select EMP_ID from EMP_MAIL where mail is null)t2 where t1.EMP_ID =t2.EMP_ID);
答案 1 :(得分:0)
好吧,我已经测试了一下,现在我将展示结果。
这是我的测试脚本(看看:根本没有索引):
create table emp_mail (
emp_id number,
mail clob
);
declare
amount_of_users constant number := 30000;
nulls_amount_percent constant number := 90;
begin
for i in 1..300 loop
insert into emp_mail
select round(dbms_random.value*amount_of_users),case when dbms_random.value < nulls_amount_percent/100 then null else 'some mail' end
from dual
connect by level <= 10000;
commit;
end loop;
end;
/
delete from emp_mail em
where mail is null
and exists (select null
from emp_mail em2
where mail is not null
and em.emp_id = em2.emp_id);
drop table emp_mail;
它创建了表(我使用CLOB创建最坏的情况),然后用常量填充表中的3M行
amount_of_users constant number := 30000;
nulls_amount_percent constant number := 90;
您可以围绕要删除的行进行播放,然后执行“删除”语句并删除该表。
我们来谈谈数字。
警告:当我谈到秒时我的意思是只删除语句,因为行生成器匿名块需要将近2分钟。
使用这些值
amount_of_users constant number := 30000;
nulls_amount_percent constant number := 90;
几乎整个表都被删除了,我可以重现你的神秘主义者27.5秒。
然后我拿
amount_of_users constant number := 30000;
nulls_amount_percent constant number := 1;
减少删除的行数,它只给我1.8秒。
让我们假设没有删除任何行:
amount_of_users constant number := 30000;
nulls_amount_percent constant number := 0;
猜猜时间? 1.1秒,据你所知,这是你的情况。
好吧,我不能给你任何建议做什么,因为你说的话可能比一个查询更全局。也许,您的数据库版本太旧了,或者它是关于硬件或其他任何东西。
如果是关于这种情况
amount_of_users constant number := 30000;
nulls_amount_percent constant number := 90;
当删除了很多行时,我可以建议将删除拆分为例如10000行部分(首先选择count(*)以了解应该运行限制删除的次数)并在每次执行后进行提交,有时候删除大量行会快得多。但是,据你所知,你删除了0行,这不应该是你的问题。