Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
![]() |
![]() |
Home -> Community -> Usenet -> c.d.o.misc -> Oracle REF CURSOR performance issue
Hi,
I'm having some trouble with a performance problem using a REF CURSOR
I have an Oracle 9i database running on Solaris 8. The query I'm
trying to tune has 2 tables (Patient and ExtPat). These tables are
joined by a key called PID (a sequence). I used sql_trace on 2
different sessions.
Session 1: I typed in the sql directly in sqlplus
Here's tkprof output
select ep.mrn,
p.LAST_NAME, p.FIRST_NAME, p.MIDDLE_NAME, p.NAME_SUFFIX, p.SSN, p.BIRTH_DATE, p.SEX_CD, p.ADDRESS_LINE1, p.ADDRESS_LINE2, p.CITY, p.STATE_CD, p.ZIP, p.HOME_PHONE, ep.DEACT_DATE, p.PID
and p.first_name like ('JOHN' || '%') and ep.EXTAPP_CD = 'SMH' and p.PID = ep.PID call count cpu elapsed disk query current rows
Parse 1 0.01 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 2 0.00 0.00 0 11 0 1
total 4 0.01 0.01 0 11 0 1
Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 66
Rows Row Source Operation
------- --------------------------------------------------- 1 TABLE ACCESS BY INDEX ROWID EXTPAT 4 NESTED LOOPS 1 TABLE ACCESS BY INDEX ROWID PATIENT 1 INDEX RANGE SCAN (object id 33005) 2 INDEX RANGE SCAN (object id 32996)
--------------------------------------------------------
Next I created a Package to use a REF CURSOR so that I can provide the Application Developers with a simple api to the database. Unfortunately, my package is performing poorly.
Here's the package.
CREATE OR REPLACE PACKAGE MPI_LOOKUP
IS
cursor c1 is
select ep.mrn,
p.LAST_NAME, p.FIRST_NAME, p.MIDDLE_NAME, p.NAME_SUFFIX, p.SSN, p.BIRTH_DATE, p.SEX_CD, p.ADDRESS_LINE1, p.ADDRESS_LINE2, p.CITY, p.STATE_CD, p.ZIP, p.HOME_PHONE, ep.DEACT_DATE, p.PID
type mpiCur is ref cursor return c1%rowtype;
procedure get_detail(p_cursor out mpiCur,
p_omegamrn in varchar2, p_facility in varchar2); procedure get_detail(p_cursor out mpiCur, p_lastname in varchar2, p_firstname in varchar2, p_facility in varchar2);
END;
/
CREATE OR REPLACE PACKAGE BODY MPI_LOOKUP
is
PROCEDURE get_detail
(
p_cursor out mpiCur,
p_omegamrn in varchar2, p_facility in varchar2 )
BEGIN
open p_cursor for
select ep.mrn, p.LAST_NAME, p.FIRST_NAME, p.MIDDLE_NAME, p.NAME_SUFFIX, p.SSN, p.BIRTH_DATE, p.SEX_CD, p.ADDRESS_LINE1, p.ADDRESS_LINE2, p.CITY, p.STATE_CD, p.ZIP, p.HOME_PHONE, ep.DEACT_DATE, p.PID
and ep.extapp_cd = p_facility and p.PID = ep.PID;
END get_detail;
PROCEDURE get_detail
(
p_cursor out mpiCur,
p_lastname in varchar2, p_firstname in varchar2, p_facility in varchar2 ) AS v_last varchar2(40); v_first varchar2(40); BEGIN select UPPER(p_lastname) || '%' into v_last from dual; select UPPER(p_firstname) || '%' into v_first from dual; open p_cursor for select ep.mrn, p.LAST_NAME, p.FIRST_NAME, p.MIDDLE_NAME, p.NAME_SUFFIX, p.SSN, p.BIRTH_DATE, p.SEX_CD, p.ADDRESS_LINE1, p.ADDRESS_LINE2, p.CITY, p.STATE_CD, p.ZIP, p.HOME_PHONE, ep.DEACT_DATE, p.PID
and p.first_name like v_first and ep.EXTAPP_CD = p_facility and p.PID = ep.PID;
END get_detail;
end mpi_lookup;
BEGIN mpi_lookup.get_detail(:b,'SMITH','JOHN','SMH'); END;
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 1 Fetch 0 0.00 0.00 0 0 0 0
total 2 0.00 0.01 0 0 0 1
Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 66
select user#
from
sys.user$ where name = 'OUTLN'
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 1 0.00 0.00 0 2 0 1
total 3 0.00 0.00 0 2 0 1
Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: SYS (recursive depth: 2)
Rows Row Source Operation
------- --------------------------------------------------- 1 TABLE ACCESS BY INDEX ROWID USER$ 1 INDEX UNIQUE SCAN (object id 44) ******************************************************************************** SELECT UPPER(:b1) || '%' from dual call count cpu elapsed disk query current rows
Parse 2 0.01 0.00 0 0 0 0 Execute 2 0.00 0.00 0 0 0 0 Fetch 2 0.00 0.00 0 2 4 2
total 6 0.01 0.00 0 2 4 2
Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 66 (recursive depth: 1)
Rows Row Source Operation
------- --------------------------------------------------- 1 TABLE ACCESS FULL DUAL ******************************************************************************** SELECT ep.mrn, p.LAST_NAME, p.FIRST_NAME, p.MIDDLE_NAME, p.NAME_SUFFIX, p.SSN, p.BIRTH_DATE, p.SEX_CD, p.ADDRESS_LINE1, p.ADDRESS_LINE2, p.CITY, p.STATE_CD, p.ZIP, p.HOME_PHONE, ep.DEACT_DATE, p.PID
and p.first_name like :b2 and ep.EXTAPP_CD = :b1 and p.PID = ep.PID call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0 Execute 1 0.01 0.00 0 0 0 0 Fetch 1 10.60 10.59 0 15133 0 1
total 3 10.61 10.60 0 15133 0 1
Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 66 (recursive depth: 1)
Rows Row Source Operation
------- --------------------------------------------------- 1 MERGE JOIN
1 SORT JOIN 1 TABLE ACCESS BY INDEX ROWID PATIENT 1 INDEX RANGE SCAN (object id 33005)
----------------------------------------------------------------
It is taking over 10 seconds to perform the same query. It ends up performing a full table scan on my ExtPat table but I'm not sure. I've joined the Patient and ExtPat table by PID which is an index in both tables.
Is there a better way in Oracle 9i to send a result set back to an application?
Thank you,
![]() |
![]() |