让我们先建一个实验表:
create table dup( id int, name nvarchar2(5), age int, primary key(id));
然后塞入一百万数据:
insert into dup select rownum, dbms_random.string('*',dbms_random.value(1,5)), dbms_random.value(18,81) from dual connect by level<1000001;
看看name不算重复的话有多少:
SQL> select count(*) from (select min(id) from dup group by name); COUNT(*) ---------- 335572 已用时间: 00: 00: 00.45
只有三十三万个,有六十七万条记录需要删除。
如果我们直接执行如下的删除,只怕会要等到猴年马月,反正我是剪完脚趾甲它还没执行完,大家有等到结果的请在留言里说明时长。
delete from dup where id not in (select min(id) from dup group by name)
所以这个方案是行不通的,删除表是CRUD里最消耗资源的,大批量删除是不推荐的,最好是找出需要的、清空原表、再塞回去。
下面就来建新表:
SQL> create table dup2 as select * from dup where id in (select min(id) from dup group by name); 表已创建。 已用时间: 00: 00: 01.15
然后清空原表:
SQL> truncate table dup; 表被截断。 已用时间: 00: 00: 00.08
再塞回去:
SQL> insert into dup select * from dup2; 已创建335572行。 已用时间: 00: 00: 00.68
以上三项加起来不到两秒,和直接delete的方案简直有天壤之别。
再看看是否还有重复项:
SQL> select count(*) from dup; COUNT(*) ---------- 335572 已用时间: 00: 00: 00.01 SQL> select count(*) from (select min(id) from dup group by name); COUNT(*) ---------- 335572 已用时间: 00: 00: 00.22 SQL> select count(*) from (select distinct name from dup); COUNT(*) ---------- 335572 已用时间: 00: 00: 00.16
三项都是一样的,自然没有重复了。
最后的结论就是 选不重复的进临时表,清空后再塞回比直接删要快且省事。
下面是实验用到的全部SQL:
SQL> insert into dup 2 select rownum, 3 dbms_random.string('*',dbms_random.value(1,5)), 4 dbms_random.value(18,81) 5 from dual 6 connect by level<1000001; 已创建1000000行。 SQL> set timing on; SQL> select count(*) from (select min(id) from dup group by name); COUNT(*) ---------- 335572 已用时间: 00: 00: 00.45 SQL> create table dup2 as select * from dup where id in (select min(id) from dup group by name); 表已创建。 已用时间: 00: 00: 01.15 SQL> truncate table dup; 表被截断。 已用时间: 00: 00: 00.08 SQL> insert into dup select * from dup2; 已创建335572行。 已用时间: 00: 00: 00.68 SQL> commit; 提交完成。 已用时间: 00: 00: 00.01 SQL> select count(*) from dup; COUNT(*) ---------- 335572 已用时间: 00: 00: 00.01 SQL> select count(*) from (select min(id) from dup group by name); COUNT(*) ---------- 335572 已用时间: 00: 00: 00.22 SQL> select count(*) from (select distinct name from dup); COUNT(*) ---------- 335572 已用时间: 00: 00: 00.16 SQL>
-END-