Blog programisty w Oracle PL/SQL

Jest to blog eksperymentatora programisty w PL/SQL dla Oracle. Wszystkie kody tutaj zamieszczone mogą być dowolnie wykorzystywane i zmieniane. A jeśli Ktoś z Gości znajdzie błąd, będę niezwykle wdzięczny...
Zapisz

Szukaj na tym blogu

środa, 24 listopada 2010

Wstawianie masowe na 5 sposobów przyrządzone

Założenia:
Celem poniższego pakietu jest porównanie szybkości różnych metod wstawiania danych do  tabeli TBL_INSERT_TEST.

CREATE TABLE TBL_INSERT_TEST
(
ID INTEGER NOT NULL,
NAME1 VARCHAR2(30 CHAR) NOT NULL,
DT1 DATE NOT NULL,
AMOUNT1 NUMBER(12,2) NOT NULL,
NAME2 VARCHAR2(30 CHAR),
DT2 DATE,
AMOUNT2 NUMBER(12,2),
NAME3 VARCHAR2(30 CHAR),
DT3 DATE,
AMOUNT3 NUMBER(12,2)
);
CREATE INDEX IDX_INSERT_TEST_NAME1 ON TBL_INSERT_TEST (NAME1);
CREATE INDEX IDX_INSERT_TEST_NAME2 ON TBL_INSERT_TEST (NAME2);
CREATE UNIQUE INDEX PK_INSERT_TEST ON TBL_INSERT_TEST (ID);
ALTER TABLE TBL_INSERT_TEST ADD ( CONSTRAINT PK_INSERT_TEST PRIMARY KEY(ID));

Przetestowałem pięć sposobów do masowego wstawiania danych. Każda metoda to osobna procedura w pakiecie, której nazwa przedstawia sposób wstawiania… Każda procedura do wstawiania ma dwa parametry:
  • pn_MaxSize NUMBER, -liczba wszystkich rekordów do wstawienia
  • pn_TransactionSize NUMBER –liczba rekordów pomiędzy kolejnymi instrukcjami COMMIT
Pierwszym krokiem procedury jest  usunięcie danych z tabeli za pomocą instrukcji TRUNCATE(szybkość). Od tego momentu rozpoczyna się pomiar czasu, a kończy po wykonaniu ostatniej instrukcji COMMIT;
Dla wstawiania z wykorzystaniem typów tablicowych stworzone zostały tabele/kolekcje - każda o wielkości pn_TransactionSize elementów.
Do testowania służy procedura PDB_TEST.

Krótki opis poszczególnych metod:

  • PDB_SIMPLE_INSERT – to najprostsza metoda INSERT zanurzony w PL/SQL. Wydajność średnia. Oracle 11g radzi optymalizuje sobie parsowanie dla powtarzających się instrukcji.W momencie zmiany struktury tabeli wymagana zmiana kodu…
  • PDB_DMBS_SQL_BIND_INSERT –chcemy wykonać jedno parsowanie przed wstawianiem, a następnie w pętli powiązać zmienne z polami tabeli i wykonywać execute. Wbrew wysokim oczekiwaniom jest to rozwiązanie najwolniejsze, dość złożone, nieodporne na zmianę struktury tabeli
  • PDB_DMBS_SQL_BIND_ARRAY_INSERT to zmodyfikowana wersja procedury PDB_DMBS_SQL_BIND_INSERT. Rozwiązanie jest szybkie, ale najbardziej złożone technicznie  Wymaga korzystania z kolekcji dbms_sql.NUMBER_TABLE, dbms_sql.DATE_TABLE, dbms_sql.VARCHAR2_TABLE. Należy uważać na maksymalną długość stringów do wstawienia – w pakiecie dbms_sql jest dziwna definicja type Varchar2_Table is table of varchar2(2000) index by binary_integer;  Należy to traktowac jako rozwiązanie działające na każdej wersji Oracle od 8i, ale nierozwojowe i bez przyszłości
  • PDB_BINDING_WITH_USING_INSERT – Wykorzystujemy NDS (Native Dynamic SQL). Rozwiązanie podobne złożonością I wydajnością do zwykłej instrukcji INSERT
  • PDB_NESTED_COLLECTION_INSERT – to rozszerzona wersja procedury
  •  PDB_BINDING_WITH_USING_INSERT – w jednym kroku dowiązujemy tabelę rekordów. Procedura jest prosta, bardzo szybka, wydajna, odporna na zmiany struktury tabeli – moja faworyta :)
CREATE OR REPLACE PACKAGE PCKG_INSERT_TEST IS
PROCEDURE PDB_SIMPLE_INSERT( pn_MaxSize NUMBER,pn_TransactionSize NUMBER);
PROCEDURE PDB_DMBS_SQL_BIND_INSERT( pn_MaxSize NUMBER,pn_TransactionSize NUMBER);
PROCEDURE PDB_BINDING_WITH_USING_INSERT( pn_MaxSize NUMBER,pn_TransactionSize NUMBER);
PROCEDURE PDB_NESTED_COLLECTION_INSERT( pn_MaxSize NUMBER,pn_TransactionSize NUMBER);
PROCEDURE PDB_DMBS_SQL_BIND_ARRAY_INSERT( pn_MaxSize NUMBER,pn_TransactionSize NUMBER);
PROCEDURE PDB_Test;
END;
/
CREATE OR REPLACE PACKAGE BODY PCKG_INSERT_TEST IS
vr_Table TBL_INSERT_TEST%ROWTYPE;
vn_Lp Integer;
vn_Start Number;
cc_Statement CONSTANT VARCHAR2(200) := 'INSERT INTO TBL_INSERT_TEST (ID, Name1,DT1, AMOUNT1, Name2,DT2, AMOUNT2, Name3,DT3, AMOUNT3) ' ||
' Values( :ID, :NAME1, :DT1, :AMOUNT1,:NAME2, :DT2, :AMOUNT2,:NAME3, :DT3, :AMOUNT3) ';
----------------------------------------------------------------------------------------------------------
PROCEDURE PDB_SIMPLE_INSERT( pn_MaxSize NUMBER,pn_TransactionSize NUMBER) IS
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE TBL_INSERT_TEST';
DBMS_OUTPUT.PUT_LINE('**********  THE SIMPLE INSERT ********');
DBMS_OUTPUT.PUT_LINE('Parametry - liczba rekordów:' || pn_MaxSize || ', liczba rekordów w transakcji ' || pn_TransactionSize );
DBMS_OUTPUT.PUT_LINE( 'START: ' || TO_CHAR(SYSDATE, 'HH:MI:SS'));
vn_Start := dbms_utility.get_time;
FOR vn_Lp IN 1..pn_MaxSize
LOOP
vr_Table.ID := vn_LP;
vr_Table.NAME1 := 'Name ' || vn_Lp ;
vr_Table.DT1 := SYSDATE;
vr_Table.AMOUNT1:= ABS(vn_Lp + (vn_Lp +2)/ (vn_Lp +3));
vr_Table.NAME2 := 'Name ' || vn_Lp;
vr_Table.DT2 := SYSDATE;
vr_Table.AMOUNT2:= ABS(vn_Lp + (vn_Lp +1)/ (vn_Lp +4));
vr_Table.NAME3 := 'Name ' || vn_Lp;
vr_Table.DT3 := SYSDATE;
vr_Table.AMOUNT3:= ABS(vn_Lp + (vn_Lp +3)/ (vn_Lp +4));
INSERT INTO TBL_INSERT_TEST (ID, Name1,DT1, AMOUNT1, Name2,DT2, AMOUNT2, Name3,DT3, AMOUNT3)
Values(vr_Table.ID,
vr_Table.NAME1, vr_Table.DT1, vr_Table.AMOUNT1,
vr_Table.NAME2, vr_Table.DT2, vr_Table.AMOUNT2,
vr_Table.NAME3, vr_Table.DT3, vr_Table.AMOUNT3);
IF vn_LP MOD pn_TransactionSize = pn_TransactionSize-1 THEN
COMMIT;
END IF;
END LOOP;
--
COMMIT;
DBMS_OUTPUT.PUT_LINE( 'KONIEC: ' || TO_CHAR(SYSDATE, 'HH:MI:SS'));
DBMS_OUTPUT.PUT_LINE( 'KONIEC PROCEDURY: ' || TO_CHAR(SYSDATE, 'HH:MI:SS'));
DBMS_OUTPUT.PUT_LINE( round( (dbms_utility.get_time- vn_start)/100, 2 ) || ' seconds...' );
END;
----------------------------------------------------------------------------------------------------------
PROCEDURE PDB_DMBS_SQL_BIND_INSERT( pn_MaxSize NUMBER,pn_TransactionSize NUMBER) IS
c INTEGER := dbms_sql.open_cursor;
fdbk INTEGER;
BEGIN
DBMS_OUTPUT.PUT_LINE('******** DBMS_SQL Bind insert **************');
DBMS_OUTPUT.PUT_LINE('Parametry - liczba rekordów:' || pn_MaxSize || ', liczba rekordów w transakcji ' || pn_TransactionSize );
EXECUTE IMMEDIATE 'TRUNCATE TABLE TBL_INSERT_TEST';
DBMS_OUTPUT.PUT_LINE( 'START: ' || TO_CHAR(SYSDATE, 'HH:MI:SS'));
vn_Start := dbms_utility.get_time;
dbms_sql.PARSE(c,cc_Statement,dbms_sql.native);
FOR vn_Lp IN 1..pn_MaxSize
LOOP
vr_Table.ID := vn_LP;
vr_Table.NAME1 := 'Name ' || vn_Lp;
vr_Table.DT1 := SYSDATE;
vr_Table.AMOUNT1:= ABS(vn_Lp + (vn_Lp +2)/ (vn_Lp +3));
vr_Table.NAME2 := 'Name ' || vn_Lp;
vr_Table.DT2 := SYSDATE;
vr_Table.AMOUNT2:= ABS(vn_Lp + (vn_Lp +1)/ (vn_Lp +4));
vr_Table.NAME3 := 'Name ' || vn_Lp;
vr_Table.DT3 := SYSDATE;
vr_Table.AMOUNT3:= ABS(vn_Lp + (vn_Lp +3)/ (vn_Lp +4));
dbms_sql.bind_variable(c, ':ID',vr_Table.ID);
dbms_sql.bind_variable(c, ':NAME1',vr_Table.NAME1);
dbms_sql.bind_variable(c, ':DT1',vr_Table.DT1);
dbms_sql.bind_variable(c, ':AMOUNT1',vr_Table.AMOUNT1);
dbms_sql.bind_variable(c, ':NAME2',vr_Table.NAME2);
dbms_sql.bind_variable(c, ':DT2',vr_Table.DT2);
dbms_sql.bind_variable(c, ':AMOUNT2',vr_Table.AMOUNT2);
dbms_sql.bind_variable(c, ':NAME3',vr_Table.NAME3);
dbms_sql.bind_variable(c, ':DT3',vr_Table.DT3);
dbms_sql.bind_variable(c, ':AMOUNT3',vr_Table.AMOUNT3);
fdbk := dbms_sql.execute(c);
IF vn_LP MOD pn_TransactionSize = 0 THEN
COMMIT;
END IF;
END LOOP;
-- Wykonanie instrukcji przy użyciu pakietu DBMS_SQL.
dbms_sql.close_cursor( c );
COMMIT;
DBMS_OUTPUT.PUT_LINE( 'KONIEC: ' || TO_CHAR(SYSDATE, 'HH:MI:SS'));
DBMS_OUTPUT.PUT_LINE( round( (dbms_utility.get_time- vn_start)/100, 2 ) || ' seconds...' );
END;
---------------------------------------------------------------------------
PROCEDURE PDB_DMBS_SQL_BIND_ARRAY_INSERT( pn_MaxSize NUMBER,pn_TransactionSize NUMBER) IS
c INTEGER := dbms_sql.open_cursor;
fdbk INTEGER;
vn_Index INTEGER := 0;
vt_IDTable      dbms_sql.NUMBER_TABLE ;
vt_NAME1Table   dbms_sql.VARCHAR2_TABLE ;
vt_DT1Table     dbms_sql.DATE_TABLE;
vt_AMOUNT1Table dbms_sql.NUMBER_TABLE ;
vt_NAME2Table   dbms_sql.VARCHAR2_TABLE ;
vt_DT2Table     dbms_sql.DATE_TABLE ;
vt_AMOUNT2Table dbms_sql.NUMBER_TABLE ;
vt_NAME3Table   dbms_sql.VARCHAR2_TABLE ;
vt_DT3Table     dbms_sql.DATE_TABLE;
vt_AMOUNT3Table dbms_sql.NUMBER_TABLE ;
---------
BEGIN
DBMS_OUTPUT.PUT_LINE('******** DBMS_SQL BIND ARRAY insert **************');
DBMS_OUTPUT.PUT_LINE('Parametry - liczba rekordów:' || pn_MaxSize || ', liczba rekordów w transakcji ' || pn_TransactionSize );
EXECUTE IMMEDIATE 'TRUNCATE TABLE TBL_INSERT_TEST';
DBMS_OUTPUT.PUT_LINE( 'START: ' || TO_CHAR(SYSDATE, 'HH:MI:SS'));
vn_Start := dbms_utility.get_time;
sys.dbms_sql.PARSE(c,cc_Statement,dbms_sql.native);
FOR vn_Lp IN 1..pn_MaxSize
LOOP
vn_Index := vn_Index + 1;
vt_IDTable(vn_Index) := vn_LP;
vt_NAME1Table(vn_Index) := 'Name ' || vn_Lp;
vt_DT1Table(vn_Index) := SYSDATE;
vt_AMOUNT1Table(vn_Index):= ABS(vn_Lp + (vn_Lp +2)/ (vn_Lp +3));
vt_NAME2Table(vn_Index) := 'Name ' || vn_Lp;
vt_DT2Table(vn_Index) := SYSDATE +1;
vt_AMOUNT2Table(vn_Index):= ABS(vn_Lp + (vn_Lp +1)/ (vn_Lp +4));
vt_NAME3Table(vn_Index) := 'Name ' || vn_Lp;
vt_DT3Table(vn_Index) := SYSDATE -1;
vt_AMOUNT3Table(vn_Index) := ABS(vn_Lp + (vn_Lp +3)/ (vn_Lp +4));
--
IF vn_Index= pn_TransactionSize OR vn_Lp = pn_TransactionSize THEN
dbms_sql.bind_array(c, ':ID',vt_IDTable,1, vn_Index);
dbms_sql.bind_array(c, ':NAME1',vt_NAME1Table,1, vn_Index);
dbms_sql.bind_array(c, ':DT1',vt_DT1Table,1, vn_Index);
dbms_sql.bind_array(c, ':AMOUNT1',vt_AMOUNT1Table,1, vn_Index);
dbms_sql.bind_array(c, ':NAME2',vt_NAME2Table,1, vn_Index);
dbms_sql.bind_array(c, ':DT2',vt_DT2Table,1, vn_Index);
dbms_sql.bind_array(c, ':AMOUNT2',vt_AMOUNT2Table,1, vn_Index);
dbms_sql.bind_array(c, ':NAME3',vt_NAME3Table,1, vn_Index);
dbms_sql.bind_array(c, ':DT3',vt_DT3Table,1, vn_Index);
dbms_sql.bind_array(c, ':AMOUNT3',vt_AMOUNT3Table,1, vn_Index);
fdbk := sys.dbms_sql.execute(c);
COMMIT;
vn_Index :=0;
END IF;
END LOOP;
-- Wykonanie instrukcji przy użyciu pakietu DBMS_SQL.
sys.dbms_sql.close_cursor( c );
COMMIT;
DBMS_OUTPUT.PUT_LINE( 'KONIEC: ' || TO_CHAR(SYSDATE, 'HH:MI:SS'));
DBMS_OUTPUT.PUT_LINE( round( (dbms_utility.get_time- vn_start)/100, 2 ) || ' seconds...' );
END;
---------------------------------------------------------------------------
PROCEDURE PDB_BINDING_WITH_USING_INSERT( pn_MaxSize NUMBER,pn_TransactionSize NUMBER)IS
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE TBL_INSERT_TEST';
DBMS_OUTPUT.PUT_LINE('*********** BINDING WITH USING CLAUSE ************');
DBMS_OUTPUT.PUT_LINE('Parametry - liczba rekordów:' || pn_MaxSize || ', liczba rekordów w transakcji ' || pn_TransactionSize );
DBMS_OUTPUT.PUT_LINE( 'START: ' || TO_CHAR(SYSDATE, 'HH:MI:SS'));
vn_Start := dbms_utility.get_time;
FOR vn_Lp IN 1..pn_MaxSize
LOOP
vr_Table.ID := vn_LP;
vr_Table.NAME1 := 'Name ' || vn_Lp;
vr_Table.DT1 := SYSDATE;
vr_Table.AMOUNT1:= ABS(vn_Lp + (vn_Lp +2)/ (vn_Lp +3));
vr_Table.NAME2 := 'Name ' || vn_Lp;
vr_Table.DT2 := SYSDATE;
vr_Table.AMOUNT2:= ABS(vn_Lp + (vn_Lp +1)/ (vn_Lp +4));
vr_Table.NAME3 := 'Name ' || vn_Lp;
vr_Table.DT3 := SYSDATE;
vr_Table.AMOUNT3:= ABS(vn_Lp + (vn_Lp +3)/ (vn_Lp +4));
EXECUTE IMMEDIATE cc_Statement using
vr_Table.ID,
vr_Table.NAME1,
vr_Table.DT1,
vr_Table.AMOUNT1,
vr_Table.NAME2,
vr_Table.DT2,
vr_Table.AMOUNT2,
vr_Table.NAME3,
vr_Table.DT3,
vr_Table.AMOUNT3;
IF vn_LP MOD pn_TransactionSize = 0 THEN
COMMIT;
END IF;
END LOOP;
COMMIT;
------
DBMS_OUTPUT.PUT_LINE( 'KONIEC: ' || TO_CHAR(SYSDATE, 'HH:MI:SS'));
DBMS_OUTPUT.PUT_LINE( round( (dbms_utility.get_time- vn_start)/100, 2 ) || ' seconds...' );
END;
---------------------------------------------------------------------------
PROCEDURE PDB_NESTED_COLLECTION_INSERT( pn_MaxSize NUMBER,pn_TransactionSize NUMBER) IS
TYPE vt_Type IS TABLE OF TBL_INSERT_TEST%ROWTYPE INDEX BY BINARY_INTEGER;
vc_InsertTest vt_Type;
vn_Index Integer := 0;
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE TBL_INSERT_TEST';
DBMS_OUTPUT.PUT_LINE('*********** NESTED COLLECTION INSERT ************');
DBMS_OUTPUT.PUT_LINE('Parametry - liczba rekordów:' || pn_MaxSize || ', liczba rekordów w transakcji ' || pn_TransactionSize );
DBMS_OUTPUT.PUT_LINE( 'START: ' || TO_CHAR(SYSDATE, 'HH:MI:SS'));
vn_Start := dbms_utility.get_time;
FOR vn_Lp IN 1..pn_MaxSize
LOOP
vn_Index := vn_Index + 1;
vr_Table.ID := vn_LP;
vr_Table.NAME1 := 'Name ' || vn_Lp;
vr_Table.DT1 := SYSDATE;
vr_Table.AMOUNT1:= ABS(vn_Lp + (vn_Lp +2)/ (vn_Lp +3));
vr_Table.NAME2 := 'Name ' || vn_Lp;
vr_Table.DT2 := SYSDATE;
vr_Table.AMOUNT2:= ABS(vn_Lp + (vn_Lp +1)/ (vn_Lp +4));
vr_Table.NAME3 := 'Name ' || vn_Lp;
vr_Table.DT3 := SYSDATE;
vr_Table.AMOUNT3:= ABS(vn_Lp + (vn_Lp +3)/ (vn_Lp +4));
vc_InsertTest(vn_Index) := vr_Table;
IF vn_Index = pn_TransactionSize OR vn_Lp = pn_MaxSize THEN
FORALL i IN 1.. vn_Index
INSERT INTO TBL_INSERT_TEST
VALUES vc_InsertTest(i);
vn_Index := 0;
COMMIT;
END IF;
END LOOP;
----
DBMS_OUTPUT.PUT_LINE( 'KONIEC: ' || TO_CHAR(SYSDATE, 'HH:MI:SS'));
DBMS_OUTPUT.PUT_LINE( round( (dbms_utility.get_time- vn_start)/100, 2 ) || ' seconds...' );
END;
---------------------------------------------------------------------------
PROCEDURE PDB_Test IS
vn_Size INTEGER := 200000;
BEGIN
PDB_SIMPLE_INSERT(vn_Size, 5000);
PDB_DMBS_SQL_BIND_INSERT(vn_Size, 5000);
PDB_BINDING_WITH_USING_INSERT(vn_Size, 5000);
PDB_NESTED_COLLECTION_INSERT( vn_Size, 5000);
PDB_DMBS_SQL_BIND_ARRAY_INSERT(vn_Size, 5000);
--
/* FOR i In 1..20 LOOP
PDB_NESTED_COLLECTION_INSERT( vn_Size, i * 1000);
PDB_DMBS_SQL_BIND_ARRAY_INSERT(vn_Size, i * 1000);
END LOOP;*/
--
END;
--------------------------------------------------------------------
END;
/


Wyniki:
Wyniki dla normalnej kompilacji bez optymalizacji
ALTER PACKAGE PCKG_INSERT_TEST COMPILE   PLSQL_CODE_TYPE =INTERPRETED    PLSQL_OPTIMIZE_LEVEL =0
**********  THE SIMPLE INSERT ********
Parametry - liczba rekordów:20000, liczba rekordów w transakcji 10000
START: 04:57:57
KONIEC: 04:58:04
KONIEC PROCEDURY: 04:58:04
6.97 seconds...
******** DBMS_SQL Bind insert **************
Parametry - liczba rekordów:20000, liczba rekordów w transakcji 10000
START: 04:58:04
KONIEC: 04:58:12
7.21 seconds...
*********** BINDING WITH USING CLAUSE ************
Parametry - liczba rekordów:20000, liczba rekordów w transakcji 10000
START: 04:58:12
KONIEC: 04:58:19
7.01 seconds...
*********** NESTED COLLECTION INSERT ************
Parametry - liczba rekordów:20000, liczba rekordów w transakcji 10000
START: 04:58:19
KONIEC: 04:58:19
0.37 seconds...
******** DBMS_SQL BIND ARRAY insert **************
Parametry - liczba rekordów:20000, liczba rekordów w transakcji 10000
START: 04:58:19
KONIEC: 04:58:20
0.42 seconds...

 Wyniki dla  kompilacji do kodu binarnego z optymalizacją  

ALTER PACKAGE PCKG_INSERT_TEST COMPILE   PLSQL_CODE_TYPE =NATIVE  PLSQL_OPTIMIZE_LEVEL =3

**********  THE SIMPLE INSERT ********
Parametry - liczba rekordów:20000, liczba rekordów w transakcji 10000
START: 04:55:06
KONIEC: 04:55:13
KONIEC PROCEDURY: 04:55:13
7.69 seconds...
******** DBMS_SQL Bind insert **************
Parametry - liczba rekordów:20000, liczba rekordów w transakcji 10000
START: 04:55:14
KONIEC: 04:55:21
7.45 seconds...
*********** BINDING WITH USING CLAUSE ************
Parametry - liczba rekordów:20000, liczba rekordów w transakcji 10000
START: 04:55:21
KONIEC: 04:55:28
6.85 seconds...
*********** NESTED COLLECTION INSERT ************
Parametry - liczba rekordów:20000, liczba rekordów w transakcji 10000
START: 04:55:28
KONIEC: 04:55:29
0.39 seconds...
******** DBMS_SQL BIND ARRAY insert **************
Parametry - liczba rekordów:20000, liczba rekordów w transakcji 10000
START: 04:55:29
KONIEC: 04:55:29
0.44 seconds...

Wnioski:

  • Najszybciej działają algorytmy wstawiania z wykorzystaniem struktur tablicowych i z kolekcji
  • Najwolniej działa algorytm z wiązaniem wartości pól na poziomie pojedynczego rekordu
  • Najbardziej rozwojowy, jako jedyny odporny na modyfikację struktury tabeli (wykorzystanie %ROWTYPE – dzięki temu kod dalej działa poprawnie) jest algorytm z wykorzystaniem kolekcji rekordów tabeli
  • Modyfikacja parametru pn_TransactionSize ma niewielki (do 20%) wpływ na szybkość  działania procedury
  • Zauważmy, że dany ciąg instrukcji INSERT z ustawionymi na stale wartościami do wstawienia wykona się dużo szybciej w SQLPlus niż jako blok PL/SQL – wynika to z faktu przełączania się pomiędzy kontekstami PL/SQL i SQL w środowisku PL/SQL

Uwagi:

  • Funkcjonalność została przetestowana na bazie Oracle 11.1.0.7
  • W ciele pakietu świadomie zrezygnowałem z aliasowania obiektów bazy danych nazwą schematu..
  • W ciele pakietu pominąłem obsługę wyjątków – koncentrowałem się na przejrzystym przedstawieniu różnych metod wstawiania
  • Do wykonania testów potrzebne są uprawnienia CREATE PROCEDURE i CREATE TABLE
  • Testy wywołuje się za pomocą poniższego bloku
BEGIN
PCKG_INSERT_TEST.PDB_TEST;
END;
  • Świetną i pouczającą zabawą jest modyfikowanie parametrów wywołania procedur do wstawiania
  • Na różnych konfiguracjach sprzętowo-programowych uzyska się różne wyniki wydajnościowe, jednakże algorytmy najszybsze pozostaną najszybsze,  co najwyżej mniej/bardziej zróżnicują się różnice pomiędzy procedurami najszybszymi a średnimi i najwolniejszą
  • Autor dołożył najwyższej staranności przy programowaniu, jednak nie gwarantuje poprawnego działania procedury.
  • Kod można dowolnie wykorzystywać i modyfikować w dowolnych celach

Brak komentarzy:

Prześlij komentarz