Ряд за строкой действительно медленный. Сделай это сразу , если сможешь; Я не могу, мне не хватает памяти, поэтому я делаю это за l oop, но за 1 миллион строк за раз. Вот как:
SQL> create table registration (coupen number);
Table created.
SQL> set timing on
SQL> begin
2 for i in 1 .. 5 loop
3 insert into registration (coupen)
4 select round(dbms_random.value(10000000,99999999),0) coupen
5 from dual
6 connect by level <= 1000000;
7 end loop;
8 end;
9 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:17.96
SQL> set timing off
SQL> select count(*) From registration;
COUNT(*)
----------
5000000
SQL>
На моем ноутбуке и базе данных XE 11g ушло ~ 18 секунд.
Если это должно быть 5 миллионов различных значений, то код должен быть несколько изменен , Я бы посоветовал вам
- вставить еще несколько строк (более 5 миллионов) (не пытайтесь избегать дублирования на этапе вставки, это займет слишком много времени для такого количества строк)
- удалить дубликаты
- удалить лишние строки (чтобы осталось 5 миллионов строк)
Вот один из вариантов (я включил подсчет и время, чтобы показать, что происходит с числом строк и посмотреть, сколько времени это займет).
create table registration (coupen number);
set serveroutput on
set timing on
declare
l_cnt number;
l_cntdis number;
begin
-- initial insert
dbms_output.put_line('Stage 1: ' || to_char(sysdate, 'hh24:mi:ss'));
for i in 1 .. 5 loop
insert into registration (coupen)
select round(dbms_random.value(10000000,99999999),0) coupen
from dual
connect by level <= 1050000; --> more than 1 million rows per loop iteration (because of duplicates)
end loop;
commit;
select count(*), count(distinct coupen)
into l_cnt, l_cntdis
from registration;
dbms_output.put_line('Stage 2: ' || to_char(sysdate, 'hh24:mi:ss') || ' total = ' || l_cnt ||', distinct = ' || l_cntdis);
execute immediate 'create index i1reg_coup on registration (coupen)';
dbms_output.put_line('Stage 3: ' || to_char(sysdate, 'hh24:mi:ss'));
-- delete remaining duplicates
delete from registration a
where a.rowid > (select min(b.rowid)
from registration b
where b.coupen = a.coupen
);
select count(*), count(distinct coupen)
into l_cnt, l_cntdis
from registration;
dbms_output.put_line('Stage 4: ' || to_char(sysdate, 'hh24:mi:ss') || ' total = ' || l_cnt ||', distinct = ' || l_cntdis);
-- delete superfluous rows (i.e. leave exactly 5.000.000 distinct rows)
delete from registration r
where r.coupen in
(select x.coupen from
(select a.coupen,
row_number() over (order by null) rn
from registration a
) x
where x.rn > 5000000
);
select count(*), count(distinct coupen)
into l_cnt, l_cntdis
from registration;
dbms_output.put_line('Stage 5: ' || to_char(sysdate, 'hh24:mi:ss') || ' total = ' || l_cnt ||', distinct = ' || l_cntdis);
end;
/
Результат:
Stage 1: 11:06:49
Stage 2: 11:07:09 total = 5250000, distinct = 5100332
Stage 3: 11:07:18
Stage 4: 11:11:17 total = 5100332, distinct = 5100332
Stage 5: 11:12:02 total = 5000000, distinct = 5000000
PL/SQL procedure successfully completed.
Elapsed: 00:05:13.57
SQL>
Чуть более 5 минут на одном ноутбуке и 11g XE. Посмотрите, является ли это приемлемым в вашем случае.