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;
Š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
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ů.
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ů.