!!! Od 1.6.2022 jsem zaměstnán na HPP. Kde? To tady nemůžu napsat (kvůli Compliance). Ale na mém Linkedin účtu (nick: Jirka Pinkas) to určitě najdete. 😁 V současnosti mám volných 10 dní, které mohu alokovat na školení 😊

cursor for loop vs. bulk collect forall

publikováno: 4.1.2016

Všude čtu jak je BULK-COLLECT výkonný, tak jsem se rozhodl to změřit. Mám data v jedné tabulce a potřebuji některé z nich získat a uložit je do druhé tabulky.

Vstupní data:

-- 1. create table
create table test_bulk_source (num number); 
create table test_bulk_target (num number);
-- 2. insert test data
declare
  maximum integer := 1000000;
begin
  FOR i IN 1..maximum LOOP
    insert into test_bulk_source values (dbms_random.random);
  END LOOP;
  commit;
end;

 

Mimochodem: nejjednodušší je udělat toto a vyprdnout se na cokoli složitějšího:

-- 3A. copy data using insert ... select statement 
-- (operation took on my computer 0,3 seconds!!!)
declare
  time_start number;
begin
  execute immediate 'truncate table test_bulk_target';
  time_start := dbms_utility.get_time();
  insert into test_bulk_target select num from test_bulk_source 
                               where num > 500000;
  commit;
  dbms_output.put_line('operation took: ' || (dbms_utility.get_time() 
                         - time_start) / 100 || ' seconds');
end;

 

Kdybychom ale potřebovali se záznamem udělat nějakou operaci, kterou v jednom SELECTu nezvládneme, pak bychom to mohli napsat takto:

-- 3B. copy data using for-loop
-- (operation took on my computer 30 seconds!!!)
declare
  time_start number;
begin
  execute immediate 'truncate table test_bulk_target';
  time_start := dbms_utility.get_time();
  for num_rec in (select num from test_bulk_source where num > 500000)
  loop
    insert into test_bulk_target values (num_rec.num);
  end loop;
  commit;
  dbms_output.put_line('operation took: ' || (dbms_utility.get_time() 
                         - time_start) / 100 || ' seconds');
end;

 

Ale skutečně výkonné řešení je toto:

-- 3C. copy data using bulk-collect-forall
-- (operation took on my computer 0,5 seconds!!!)
declare
  time_start number;
  cursor c is select num from test_bulk_source where num > 500000;
  type number_collection is table of number;
  numbers number_collection;
begin
  execute immediate 'truncate table test_bulk_target';
  time_start := dbms_utility.get_time();
  open c;
  fetch c bulk collect into numbers;
  forall i in numbers.first .. numbers.last
    insert into test_bulk_target values(numbers(i));
  close c;
  commit;
  dbms_output.put_line('operation took: ' || (dbms_utility.get_time() 
                         - time_start) / 100 || ' seconds');
end;

Reference

Školení bych doporučil všem lidem, kteří se chtějí dozvědět něco o DB. Na školeni jsem přišel, jako úplný nováček, co se týče práci s DB a odcházel plný dojmů a

Ondřej

Osobně jsem trošku stále váhající, jestli a jak moc SQL použít. Ale určitě hlavní je to, že se teď už tolik nebojím. Je to pro mě začátek dlouhé cesty. Osobně

Robert

Zajímavé školení, které vhodně kombinovalo teorii a praxi.

Ministerstvo financí
Jan


Novinky

9.9.2021: SQL Developer & Remote Debug

22.3.2019: Termíny SQL školení léto 2019
Nové termíny!!!

3.1.2018: Oracle XE 12c nebude, místo toho bude Oracle XE 18c
V roce 2018 nás čeká nová XE verze a nové verzování