CREATE TABLE employees AS SELECT * FROM hr.employees
Table created.
Traditional Approach to Row Retrieval
CREATE OR REPLACE PACKAGE emplu1
IS
FUNCTION onerow (
employee_id_in IN employees.employee_id%TYPE)
RETURN employees%ROWTYPE;
END;
Package created.
Query Every Time
CREATE OR REPLACE PACKAGE BODY emplu1
IS
FUNCTION onerow (
employee_id_in IN employees.employee_id%TYPE)
RETURN employees%ROWTYPE
IS
onerow_rec employees%ROWTYPE;
BEGIN
SELECT *
INTO onerow_rec
FROM employees
WHERE employee_id = employee_id_in;
RETURN onerow_rec;
END;
END;
Package Body created.
A PGA Caching Package
CREATE OR REPLACE PACKAGE emplu2
IS
FUNCTION onerow (
employee_id_in IN employees.employee_id%TYPE)
RETURN employees%ROWTYPE;
END;
Package created.
Super Fast, PGA-Based Lookup
CREATE OR REPLACE PACKAGE BODY emplu2
IS
TYPE employee_tt IS TABLE OF employees%ROWTYPE
INDEX BY PLS_INTEGER;
employee_cache employee_tt;
FUNCTION onerow (
employee_id_in IN employees.employee_id%TYPE)
RETURN employees%ROWTYPE
IS
BEGIN
RETURN employee_cache (employee_id_in);
END onerow;
PROCEDURE load_cache
IS
BEGIN
FOR rec IN (SELECT * FROM employees)
LOOP
employee_cache (rec.employee_id) := rec;
END LOOP;
END load_cache;
BEGIN
load_cache;
END emplu2;
Package Body created.
Add That Keyword!
CREATE OR REPLACE PACKAGE emplu11g
IS
FUNCTION onerow (
employee_id_in IN employees.employee_id%TYPE)
RETURN employees%ROWTYPE
RESULT_CACHE;
END;
Package created.
No Change to Body of Function
CREATE OR REPLACE PACKAGE BODY emplu11g
IS
FUNCTION onerow (
employee_id_in IN employees.employee_id%TYPE)
RETURN employees%ROWTYPE
RESULT_CACHE
IS
onerow_rec employees%ROWTYPE;
BEGIN
SELECT *
INTO onerow_rec
FROM employees
WHERE employee_id = employee_id_in;
RETURN onerow_rec;
END;
END;
Package Body created.
Compare Performance of Different Approaches
CREATE OR REPLACE PROCEDURE test_emplu (
counter IN INTEGER
, employee_id_in IN employees.employee_id%TYPE := 138
)
IS
emprec employees%ROWTYPE;
l_start TIMESTAMP;
PROCEDURE start_timer
IS
BEGIN
l_start := SYSTIMESTAMP;
END start_timer;
PROCEDURE show_elapsed_time ( message_in IN VARCHAR2 )
IS
BEGIN
DBMS_OUTPUT.put_line (
CASE
WHEN message_in IS NULL THEN 'Completed in:'
ELSE '"' || message_in || '" completed in: '
END
|| REGEXP_SUBSTR (SYSTIMESTAMP - l_start,
'([1-9][0-9:]*|0)\.\d{3}')
|| ' seconds');
/* Reset timer */
start_timer;
END show_elapsed_time;
BEGIN
start_timer;
FOR i IN 1 .. counter
LOOP
emprec := emplu11g.onerow (employee_id_in);
END LOOP;
show_elapsed_time ('Oracle 11g result cache');
FOR i IN 1 .. counter
LOOP
emprec := emplu2.onerow (employee_id_in);
END LOOP;
show_elapsed_time ('Cache table in PGA memory');
FOR i IN 1 .. counter
LOOP
emprec := emplu1.onerow (employee_id_in);
END LOOP;
show_elapsed_time ('Execute query each time');
END;
Procedure created.
Let 'er Rip!
BEGIN
test_emplu (
counter => 100000
, employee_id_in => 138);
END;
"Oracle 11g result cache" completed in: 6:59:59.827 seconds
"Cache table in PGA memory" completed in: 6:59:59.959 seconds
"Execute query each time" completed in: 6:59:54.895 seconds