!!! 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í mi pomohlo ujasnit si jak má správně probíhat testování kódu, představilo užitečné knihovny a nástroje. Vše bylo podáno zábavnou formou, takže nebyl problém udržet pozornost. Navíc byl výhodou dostatek

Certicon
David

Jedno z nejlepších školení za poslední roky. Kromě seznámení se Springem apod. mě velmi příjemně překvapila hluboká znalost probírané látky a schopnost ji srozumitelně vysvětlit v případě ad hoc dotazů.

Jaroslav

Přestože jsem Cčkař, tak jsem se na školení JUnit dozvěděl nové věci. Zejména co se týče metodiky jednotkového testování a některých odborných termínů.

Retia
Jaromír


Novinky

25.12.2023: testcontainers pro lokální vývoj

25.12.2023: Kubernetes & Prometheus Documentary

9.8.2023: Rancher Desktop 2023