Skip to Main Content
  • Questions
  • Why Explain Plan miss table in function

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Smith.

Asked: March 06, 2016 - 2:57 pm UTC

Last updated: March 09, 2017 - 1:49 pm UTC

Version: 11g2

Viewed 1000+ times

You Asked

How to collect explain plan on table used in function call by procedure?

Suppose I written simple sql query below.

select t.tid,t.tname,(select emp_id from emp e where e.emp_id=t.emp_id) from transaction t;

And following Explain plan is for above query

----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 11582 | 210566 | 3 (0)| 00:00:01 |
|* 1 | INDEX UNIQUE SCAN| PK_EMP | 1 | 2 | 1 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| transaction | 11582 | 210566 | 3 (0)| 00:00:01 |

Now same thing do using store procedure then plan is same.

create or replace procedure empDetails(vrec out sys_refcursor)
is
begin
open vrec for
select t.tid,t.tname,
(select emp_id from emp e where e.emp_id=t.emp_id)
from transaction t;
end;

I modified stored procedure and used the following function

create or replace function getEmp(e number)
return varchar2
is
ae varchar2;
begin`
select emp_id into ae from emp e where e.emp_id =e;
return ve;
end;


create or replace procedure empDetail(vrec out sys_refcursor)
is
begin
open vrec for
select t.tid,t.tname,getEmp(t.emp_id) from transaction t;
end;

And Last Explain is

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100)| |
--------------------------------------------------------------------------
| 1 | TABLE ACCESS FULL| TRANSACTION | 11582 | 210566 | 3 (0)| 00:00:01 |

My questions are

Why plan getting wrong?
Is there another way to get correct detail plan?
Is there a different tool to display the plan?

and Connor said...

The plan is not "wrong" as such, its a reflection of the queries that can be seen *within* the SQL your are running.

The function you call could be

- running other sql
- calling other functions
- running java
- calling an external webservice
- doing an ftp
etc etc etc

We can't reasonably follow the path of every recursive code path, so we restrict ourselves to the SQL that is readily visible in the SQL you are explaining.

Hope this helps.

Rating

  (2 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Other Alternative Tool

Rajeshwaran, Jeyabal, March 07, 2016 - 6:56 am UTC

Is there a different tool to display the plan?

Yes, Tkprof display it well.

set feedback off
drop table t1 purge;
drop table t2 purge;
create table t1 as select * from all_users;
create table t2 as select * from all_objects;
alter table t1 add constraint t1_pk
primary key(username);
alter table t2 add constraint t2_fk
foreign key(owner)
references t1 
modify owner not null;
begin 
 dbms_stats.gather_table_stats(user,'T1');
 dbms_stats.gather_table_stats(user,'T2');
end;
/
create or replace function foo(p_owner varchar2) 
return number as 
 l_object_id int;
begin 
 select max(object_id) 
 into l_object_id
 from t2 
 where owner = p_owner;
 return l_object_id;
end;
/
create or replace procedure prc as 
 cursor c is select username, foo(username)
  from t1
 where user_id > 55;
 r c%rowtype;
begin 
 open c ;
 loop
  fetch c into r ;
  exit when c%notfound;
 end loop;
 close c;
end;
/
exec prc;
set feedback on 

********************************************************************************

SQL ID: 7f9fb6qhgrygy Plan Hash: 3617692013

SELECT USERNAME, FOO(USERNAME) 
FROM
 T1 WHERE USER_ID > 55


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       24      0.01       0.00          0         25          0          23
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total       26      0.01       0.00          0         25          0          23

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 90     (recursive depth: 1)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
        23         23         23  TABLE ACCESS FULL T1 (cr=25 pr=0 pw=0 time=29 us cost=4 size=494 card=38)

********************************************************************************


recursive depth: 1 - Tell us that this sql is executed from either procedure/function/packages.

********************************************************************************

SQL ID: 0pt4k5fgquawx Plan Hash: 3321871023

SELECT MAX(OBJECT_ID) 
FROM
 T2 WHERE OWNER = :B1 


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.01       0.00          0          0          0           0
Execute     23      0.00       0.00          0          0          0           0
Fetch       23      0.04       0.05          0      27899          0          23
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total       47      0.06       0.06          0      27899          0          23

Misses in library cache during parse: 1
Misses in library cache during execute: 1
Optimizer mode: ALL_ROWS
Parsing user id: 90     (recursive depth: 2)
Number of plan statistics captured: 1

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  SORT AGGREGATE (cr=1213 pr=0 pw=0 time=2753 us)
         0          0          0   TABLE ACCESS FULL T2 (cr=1213 pr=0 pw=0 time=2748 us cost=630 size=29975 card=2725)




********************************************************************************


recursive depth: 2 - Tell us that this sql is invoked from sql executed from procedure/function/packages.

A reader, March 09, 2017 - 4:43 am UTC

"We can't reasonably follow the path of every recursive code path, so we restrict ourselves to the SQL that is readily visible in the SQL you are explaining."

If I run procedure and other plsql object from front-end application so can i capture my sql statement and other session details?
session detail may be active user or inactive user.
Chris Saxon
March 09, 2017 - 1:49 pm UTC

You can run a session trace to capture all the SQL, then parse it with TKPROF as described above:

https://blogs.oracle.com/sql/entry/how_to_create_an_execution#tkprof

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library