Kontaktní osoba:
Ing. Jiří Pinkas
Mobil: +420 774 912 047

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;




comments powered by Disqus


Reference

Expobank CZ, a.s.

" Co se mi na školení líbilo byla neformální atmosféra, která panovala po celou dobu školení. Dále bych pochválil lektora za pohotové odpovědi a také za příklady ze života/ praxe (čím " podrobnosti ...

Tomáš

Commerz Systems

" Skoleni se mi moc libilo. Hodne praktickych prikladu na pocitaci, kde clovek rychlej pochopil danou problematiku. V pripade nepochopeni byl lektor ochoten poradit a vysvetlit konkretni pripad detailneji. Skoleni budu " podrobnosti ...

Andrea

Buřinka

" Školení na psaní SQL dotazů předčilo mé očekávání. Jirka probírá teorii po blocích, po každém bloku účastníci zpracovávají praktické příklady. Při zpracování praktických příkladů jsem velmi ocenila individuální " podrobnosti ...

Zuzana


Novinky

4.4.2017: SAP HANA & Veverka (SQuirrel SQL)

Oficiální SAP HANA studio funguje, ale je hrozně pomalé. Další z nástrojů, kde je možné rozchodit SAP HANA je Veverka (SQuirrel SQL) podrobnosti ...

25.3.2017: SAP HANA referenční příručky

V současnosti je trošku složitější najít na webu referenční příručku k SAP HANA SQL, proto sem dávám odkazy. podrobnosti ...

6.3.2017: SAP HANA 2.0, express edition + SAP HANA studio instalace

Rychlé how-to podrobnosti ...