Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.misc -> Re: Oracle REF CURSOR performance issue

Re: Oracle REF CURSOR performance issue

From: Marco Casale <mjcasale_at_yahoo.com>
Date: 17 Jan 2002 09:19:11 -0800
Message-ID: <f79df195.0201170919.565316db@posting.google.com>


Thanks, Jonathan for your quick reply.

I took your advice and used a SQL Hint /* INDEX(ep index_name) */ on my select statement and now the optimizer performs an index scan. My package performance is now equal to the sql statement performed directly in sql-plus.

Thanks again,

"Jonathan Lewis" <jonathan_at_jlcomp.demon.co.uk> wrote in message news:<1011208705.6339.0.nnrp-01.9e984b29_at_news.demon.co.uk>...
> There are several possible problems. Without
> a costed execution plan it is hard to determine
> exactly why Oracle has taken a specific path.
>
> Most importantly, though, how accurate are your
> statistics. It looks as if Oracle thinks your extpat
> table is quite small.
>
> Secondly, bind variables with LIKE are always
> a bit of a problem.
>
> It is a bit of a puzzle, though, as Oracle 9 is
> supposed to peek inside bind variables on the
> first execution and derive a plan from the values
> it finds - so you would expect it to use the same
> plan in both cases/
>
> Quick and dirty fix - things to try:
>
> set the hint /*+ first_rows */
> set hint /*+ use_nl(ep) use_nl(p) */
>
>
> --
> Jonathan Lewis
> http://www.jlcomp.demon.co.uk
>
> Now running 3-day intensive seminars
> http://www.jlcomp.demon.co.uk/seminar.html
>
> Host to The Co-Operative Oracle Users' FAQ
> http://www.jlcomp.demon.co.uk/faq/ind_faq.html
>
> Author of:
> Practical Oracle 8i: Building Efficient Databases
>
>
> Marco Casale wrote in message ...
> >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
> > from extpat ep, patient p
> > where p.last_name like ('SMITH' || '%')
> > 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
> > from extpat ep, patient p;
> >
> >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 )
> >AS
> >
> >
> >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
> > from extpat ep, patient p
> > where ep.mrn = LPAD(p_omegamrn,12,0)
> > 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
> > from extpat ep, patient p
> > where p.last_name like v_last
> > and p.first_name like v_first
> > and ep.EXTAPP_CD = p_facility
> > and p.PID = ep.PID;
> >
> >END get_detail;
> >
> >end mpi_lookup;
> >------------------------------------------------------------
> >Here's the output from tkprof
> >
> >
> >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
> > from extpat ep, patient p
> > where p.last_name like :b3
> > 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
> > 963386 TABLE ACCESS BY INDEX ROWID EXTPAT
> >1928434 INDEX FULL SCAN (object id 32996)
> > 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,
> >
> >- Marco
Received on Thu Jan 17 2002 - 11:19:11 CST

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US