Лучший и быстрый способ вставки записей миллионов в oracle - PullRequest
0 голосов
/ 27 апреля 2020

Я хочу вставить 5 миллионов уникальных случайных чисел в таблицу oracle. каждое случайное число имеет 8 цифр. вот мой код

DECLARE I INT;
J INT;
gen_coupen varchar2(8);
check_coupen varchar2(8);

 BEGIN

 j :=1;

FOR I IN J..:TO_COUPEN LOOP
select round(dbms_random.value(10000000,99999999),0) into :gen_coupen from dual;

    select count(*) into :check_coupen from registration where coupen=:gen_coupen;
    if (:check_coupen=0) and LENGTH(:gen_coupen)=8 then
  insert into registration (coupen)
    values(:gen_coupen);
    commit;
end if;

этот код работает нормально, но для его вставки требуется много времени, есть ли самый быстрый способ вставить записи в 5 миллионов.

1 Ответ

1 голос
/ 27 апреля 2020

Ряд за строкой действительно медленный. Сделай это сразу , если сможешь; Я не могу, мне не хватает памяти, поэтому я делаю это за 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. Посмотрите, является ли это приемлемым в вашем случае.

...