For r in (select) loop: execution plan question
Hi there,
I have a procedure which does the following (on Oracle 11.1.0.7):
begin
for r in (select col1,max(col2) as col2 from tab@remote_db group by col1 ) loop
update tab2
set col_a = r.co1
where col_b = r.col2;
commit;
end loop;
end;The subselect from the remote table delivers about 4000 rows.
When executing fast, the procedure runs about 20 seconds, the trace shows that the select is executed 1 time, fetches 49 times. The update executes 4000 times.
When executing slow, the procedure runs about 20 minutes (!), the trace shows that the select is executed 1 times, fetches 4000 times. The update executes 4000 times.
This happens without changing the code, from the same client (sqlplus on the server, same version as database).
Can anyone probably give me a clue how I could track down the plsql execution steps like the optimizer trace that let you see why a certain sqlplan was not taken or what might cause that change in behavior?
I cannot produce that behavior at will - most times the procedure runs fast.
thanks,
Heimo
Hi again,
regarding the "faulty test" and what is fastest: user tested both versions and came up with the for-loop to satisfy him best. I would, of course, utilize event 10046 and tkprof and a repeatable dataset to have solid data. Sorry for not setting enough emphasis on my real question, which is described in the following.
But, and that is what is really causing awkward feelings for me: when doing plain sql, I can use events 10046, 10053 and learn from the tracefiles why a decision was taken (now that is making me feel good, actually). But when it comes to plsql, I have not yet such a handy toolset that helps me understand what influences the plsql-engine to go this or that way.
Thus, I valued the posts pointing to dbms_trace and plsql_optimization_level as helpful answers.
Because of that I learned about the views %_PLSQL_OBJECT_SETTINGS and remembered to check for other plsql-initora settings.
I also verified that neither the 10046 nor the 10053 trace files contain any reference to plsql-parameters/settings, and that the 10053 trace only shows the subselect and update, but no info if it would "bulkify" or not.
Meanwhile I did start to utilize dbms_trace (which causes the statement to go the unbulkifyed by the way) and maybe I can learn from that output or from following posts?
best regards
Heimo
Similar Messages
-
Different 'execution plans' for same sql in 10R2
DB=10.2.0.5
OS=RHEL 3
Im not sure of this, but seeing different plans for same SQL.
select sql_text from v$sqlarea where sql_id='92mb4z83fg4st'; <---TOP SQL from AWR
SELECT /*+ OPAQUE_TRANSFORM */ "ENDUSERID","LASTLOGINATTEMPTTIMESTAMP","LOGINSOURCECD","LOGINSUCCESSFLG",
"ENDUSERLOGINATTEMPTHISTORYID","VERSION_NUM","CREATEDATE"
FROM "BOMB"."ENDUSERLOGINATTEMPTHISTORY" "ENDUSERLOGINATTEMPTHISTORY";
SQL> set autotrace traceonly
SQL> SELECT /*+ OPAQUE_TRANSFORM */ "ENDUSERID","LASTLOGINATTEMPTTIMESTAMP","LOGINSOURCECD","LOGINSUCCESSFLG",
"ENDUSERLOGINATTEMPTHISTORYID","VERSION_NUM","CREATEDATE"
FROM "BOMB"."ENDUSERLOGINATTEMPTHISTORY" "ENDUSERLOGINATTEMPTHISTORY"; 2 3
1822203 rows selected.
Execution Plan
Plan hash value: 568996432
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1803K| 75M| 2919 (2)| 00:00:36 |
| 1 | TABLE ACCESS FULL| ENDUSERLOGINATTEMPTHISTORY | 1803K| 75M| 2919 (2)| 00:00:36 |
Statistics
0 recursive calls
0 db block gets
133793 consistent gets
0 physical reads
0 redo size
76637183 bytes sent via SQL*Net to client
1336772 bytes received via SQL*Net from client
121482 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1822203 rows processed
===================================== another plan ===============
SQL> select * from TABLE(dbms_xplan.display_awr('92mb4z83fg4st'));
15 rows selected.
Execution Plan
Plan hash value: 3015018810
| Id | Operation | Name |
| 0 | SELECT STATEMENT | |
| 1 | COLLECTION ITERATOR PICKLER FETCH| DISPLAY_AWR |
Note
- rule based optimizer used (consider using cbo)
Statistics
24 recursive calls
24 db block gets
49 consistent gets
0 physical reads
0 redo size
1529 bytes sent via SQL*Net to client
492 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
15 rows processed
=========second one shows only 15 rows...
Which one is correct ?Understood, second plan is for self 'dbms_xplan'.
Anyhow I opened a new session where I did NOT on 'auto-trace'. but plan is somewhat than the original.
SQL> /
PLAN_TABLE_OUTPUT
SQL_ID 92mb4z83fg4st
SELECT /*+ OPAQUE_TRANSFORM */ "ENDUSERID","LASTLOGINATTEMPTTIMESTAMP","LOGINSOURCECD","
LOGINSUCCESSFLG","ENDUSERLOGINATTEMPTHISTORYID","VERSION_NUM","CREATEDATE" FROM
"BOMB"."ENDUSERLOGINATTEMPTHISTORY" "ENDUSERLOGINATTEMPTHISTORY"
Plan hash value: 568996432
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
PLAN_TABLE_OUTPUT
| 0 | SELECT STATEMENT | | | | 2919 (100)| |
| 1 | TABLE ACCESS FULL| ENDUSERLOGINATTEMPTHISTORY | 1803K| 75M| 2919 (2)| 00:00:36 |
15 rows selected.
I am just wondering, which plan is the accurate and which I need to believe ? -
How to fix different execution plan for different bind variable values?
Please find the below query. The execution plan is fine. The problem That I am facing is in some cases for different bind variable values execution plan gets changed and degrades performance. I have used 6 tables here and all of the tables have histogram on all columns. Database version is Oracle 10g and the value of method_opt is 'For all columns size auto'
SELECT l.LineNumber INTO :b0
FROM Lines l ,LineVersions lv ,Statuses s
WHERE (((((((((((l.serviceContractId=:b1 AND l.LineId<>:b2)
AND lv.LineId=l.LineId) AND lv.StatusId=s.StatusId)
AND s.Code IN ('EPR','ERE','EEP','ERP','PRP','PRD','AAC'))
AND NOT (s.CODE='AAC' AND lv.activeto<TO_DATE(:b3,:b4)))
AND lv.EquipmentDetailId=:b5) AND lv.RouteDetailId=:b6)
AND (lv.cargoDetailId=:b7 OR lv.cargoDetailId IN
(SELECT i_cd1.cargoDetailId
FROM CargoDetails i_cd1 ,CargoDetails i_cd2 ,CargoCommodities i_cc1 ,
CargoCommodities i_cc2 WHERE
((((((i_cd2.cargoDetailId=:b7 AND i_cd1.cargoDetailId<>:b7)
AND i_cd1.ServiceContractId=:b1) AND i_cd1.cargoTypeId=i_cd2.cargoTypeId)
AND i_cc1.cargoDetailId=i_cd1.cargoDetailId)
AND i_cc2.cargoDetailId=i_cd2.cargoDetailId)
AND i_cc1.commodityId=i_cc2.commodityId))))
AND ((lv.customerGroupId IS NULL AND :b11=0) OR lv.customerGroupId IN
(SELECT cgm1.customerGroupId
FROM CustomerGroupMembers cgm1 ,CustomerGroupMembers cgm2 ,CustomerGroups cg1
WHERE (((cgm2.customerGroupId=:b11 AND cgm1.customerNoId=cgm2.customerNoId)
AND cg1.CustomerGroupId=cgm1.CustomerGroupId)
AND cg1.ServiceContractId=l.ServiceContractId)))) AND lv.linetype='C')
AND ROWNUM=1)
After searching in several blogs I have found the below solutions. Please see it and let me know it is correct or not
Solution 1:-Get rid of histogram that does nothing but messes up execution plan by giving below command
exec dbms_stats.gather_table_stats(owner, tablename, method_opt => 'for all columns size 1', cascade => true);
As 6 tables are there I need to execute above command 6 times.
Solution 2:- Use stored outline. Not sure how to get the best execution plan.
I am looking for answers ASAP. Thanks in advanceAs you have probably read, bind variables and histograms do not mix well.
Histograms suggest that you have skew in your data such that different values should get different plans
Bind variables exist so that SQL with different supplied values can be shared.
Mix the two together and at parse time with bind variable peeking you get plans for specific values shared for all values.
The solutions you have mentioned are the common approaches, together with a third - use literals not binds if you've got data skew (i.e. your histograms are justified) and don't want shared SQL.
I would have thought that getting rid of some of these histograms may be the right approach if you're none of your application SQL is using literals to benefit from them.
Can you confirm your version of Oracle.
Further reading:
http://jonathanlewis.wordpress.com/2009/05/06/philosophy-1/
http://structureddata.org/2008/03/26/choosing-an-optimal-stats-gathering-strategy/
http://richardfoote.wordpress.com/2008/01/04/dbms_stats-method_opt-default-behaviour-changed-in-10g-be-careful/ -
Very different execution plan in Oracle 10g vs. 9i
Good afternoon,
A few days ago I migrated an Oracle database 9i to 10g.
Right now I have an exact copy of the 9i instance running on another machine.
I noticed that the time for some queries take much more. For example, when comparing the execution plan for this query on the instance with Oracle 9i and Oracle 10g instance, I see that the cost in 10g is 94981765382, while in 9i is 120106.
Any idea what might be happening?
Execution Plan Oracle 9: http://blog.davidlozanolucas.com/uploads/execution_plan_Oracle_9i.jpg
Execution Plan Oracle 10g: http://blog.davidlozanolucas.com/uploads/execution_plan_Oracle_10g.jpg
Edited by: david_lozano_lucas on Dec 14, 2011 4:54 PMSorry,
Here are the details.
For Oracle 9i:
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
| 0 | SELECT STATEMENT | | 16M| 3675M| | 120K (0)| | | | | |
|* 1 | FILTER | | | | | | | | | | |
|* 2 | HASH JOIN | | 16M| 3675M| | 120K (0)| | | 03,09 | P->S | QC (RAND) |
| 3 | TABLE ACCESS FULL | ORG_LOC_DM | 2261 | 13566 | | 8 (0)| | | 03,01 | S->P | HASH |
|* 4 | HASH JOIN OUTER | | 16M| 3582M| 1023M| 120K (0)| | | 03,08 | P->P | HASH |
|* 5 | HASH JOIN OUTER | | 16M| 2783M| 1041M| 102K (0)| | | 03,08 | PCWP | |
|* 6 | HASH JOIN OUTER | | 16M| 2521M| 715M| 69515 (0)| | | 03,08 | PCWP | |
| 7 | PARTITION RANGE ALL | | | | | | 1 | 14 | 03,08 | PCWP | |
| 8 | TABLE ACCESS FULL | SURT_SKU_LD_DM | 16M| 1922M| | 60988 (0)| 1 | 14 | 03,04 | P->P | HASH |
| 9 | VIEW | | 909K| 33M| | | | | 03,05 | P->P | HASH |
| 10 | SORT GROUP BY | | 909K| 19M| 62M| 1553 (0)| | | 03,05 | PCWP | |
|* 11 | HASH JOIN | | 909K| 19M| | 164 (0)| | | 03,05 | PCWP | |
|* 12 | TABLE ACCESS FULL| ORG_LOC_DM | 1131 | 6786 | | 8 (0)| | | 03,00 | S->P | HASH |
|* 13 | TABLE ACCESS FULL| INV_MOVE_SKU_LCM_DM | 909K| 13M| | 154 (0)| 60 | 60 | 03,02 | P->P | HASH |
|* 14 | TABLE ACCESS FULL | SURT_SKU_LCM_DM | 16M| 260M| | 6457 (0)| 59 | 59 | 03,06 | P->P | HASH |
| 15 | VIEW | | 1795K| 89M| | | | | 03,07 | P->P | HASH |
| 16 | SORT GROUP BY | | 1795K| 63M| 233M| 4565 (0)| | | 03,07 | PCWP | |
|* 17 | TABLE ACCESS FULL | SLS_SKU_LCM_DM | 1795K| 63M| | 599 (0)| 60 | 60 | 03,03 | P->P | HASH |
| 18 | NESTED LOOPS | | 1 | 16 | | 7 (15)| | | | | |
| 19 | TABLE ACCESS FULL | MAINT_LOAD_DT | 1 | 8 | | 1 (0)| | | | | |
|* 20 | INDEX RANGE SCAN | DAY_IDNT_I1 | 1 | 8 | | 1 (0)| | | | | |
Predicate Information (identified by operation id):
1 - filter("SYS_ALIAS_1"."DAY_IDNT"= (SELECT /*+ */ :B1 FROM "RDW91_DM"."MAINT_LOAD_DT" "Y","RDW91_DM"."TIME_DAY_DM" "X" WHERE
"X"."DAY_DT"="Y"."CURR_LOAD_DT"))
2 - access("SYS_ALIAS_1"."LOC_KEY"="G"."LOC_KEY")
4 - access("SYS_ALIAS_1"."LOC_KEY"="I"."LOC_KEY"(+) AND "SYS_ALIAS_1"."SKU_KEY"="I"."SKU_KEY"(+))
5 - access("SYS_ALIAS_1"."LOC_KEY"="B"."LOC_KEY"(+) AND "SYS_ALIAS_1"."SKU_KEY"="B"."SKU_KEY"(+))
6 - access("SYS_ALIAS_1"."LOC_KEY"="J"."LOC_KEY"(+) AND "SYS_ALIAS_1"."SKU_KEY"="J"."SKU_KEY"(+))
11 - access("A"."LOC_KEY"="B"."LOC_KEY")
12 - filter("B"."LOC_TYPE_CDE"='W')
13 - filter("A"."CMTH_IDNT"=201112)
14 - filter("B"."CMTH_IDNT"(+)=201111)
17 - filter("SLS_SKU_LCM_DM"."CMTH_IDNT"=201112)
20 - access("X"."DAY_DT"="Y"."CURR_LOAD_DT")
For 10g:
PLAN_TABLE_OUTPUT
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
| 0 | SELECT STATEMENT | | 16M| 3685M| | 94G| | | | | |
| 1 | FILTER | | | | | | | | | | |
| 2 | PX COORDINATOR | | | | | | | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10008 | 16M| 3685M| | 94G| | | Q1,08 | P->S | QC (RAND) |
| 4 | BUFFER SORT | | 16M| 3685M| | | | | Q1,08 | PCWP | |
| 5 | NESTED LOOPS OUTER | | 16M| 3685M| | 94G| | | Q1,08 | PCWP | |
| 6 | HASH JOIN | | 16M| 3424M| | 201K| | | Q1,08 | PCWP | |
| 7 | BUFFER SORT | | | | | | | | Q1,08 | PCWC | |
| 8 | PX RECEIVE | | 2261 | 13566 | | 8 | | | Q1,08 | PCWP | |
| 9 | PX SEND HASH | :TQ10001 | 2261 | 13566 | | 8 | | | | S->P | HASH |
| 10 | TABLE ACCESS FULL | ORG_LOC_DM | 2261 | 13566 | | 8 | | | | | |
| 11 | PX RECEIVE | | 16M| 3332M| | 201K| | | Q1,08 | PCWP | |
| 12 | PX SEND HASH | :TQ10007 | 16M| 3332M| | 201K| | | Q1,07 | P->P | HASH |
| 13 | HASH JOIN OUTER BUFFERED | | 16M| 3332M| 982M| 201K| | | Q1,07 | PCWP | |
| 14 | HASH JOIN OUTER | | 16M| 2733M| 735M| 127K| | | Q1,07 | PCWP | |
| 15 | PX RECEIVE | | 16M| 1934M| | 75785 | | | Q1,07 | PCWP | |
| 16 | PX SEND HASH | :TQ10004 | 16M| 1934M| | 75785 | | | Q1,04 | P->P | HASH |
| 17 | PX BLOCK ITERATOR | | 16M| 1934M| | 75785 | 1 | 14 | Q1,04 | PCWC | |
| 18 | TABLE ACCESS FULL | SURT_SKU_LD_DM | 16M| 1934M| | 75785 | 1 | 14 | Q1,04 | PCWP | |
| 19 | PX RECEIVE | | 1450K| 71M| | 3892 | | | Q1,07 | PCWP | |
| 20 | PX SEND HASH | :TQ10005 | 1450K| 71M| | 3892 | | | Q1,05 | P->P | HASH |
| 21 | VIEW | | 1450K| 71M| | 3892 | | | Q1,05 | PCWP | |
| 22 | SORT GROUP BY | | 1450K| 53M| 188M| 3892 | | | Q1,05 | PCWP | |
| 23 | PX RECEIVE | | 1450K| 53M| | 562 | | | Q1,05 | PCWP | |
| 24 | PX SEND HASH | :TQ10002 | 1450K| 53M| | 562 | | | Q1,02 | P->P | HASH |
| 25 | PX BLOCK ITERATOR | | 1450K| 53M| | 562 | 60 | 60 | Q1,02 | PCWC | |
| 26 | MAT_VIEW ACCESS FULL| SLS_SKU_LCM_DM | 1450K| 53M| | 562 | 60 | 60 | Q1,02 | PCWP | |
| 27 | PX RECEIVE | | 652K| 24M| | 1150 | | | Q1,07 | PCWP | |
| 28 | PX SEND HASH | :TQ10006 | 652K| 24M| | 1150 | | | Q1,06 | P->P | HASH |
| 29 | VIEW | | 652K| 24M| | 1150 | | | Q1,06 | PCWP | |
| 30 | SORT GROUP BY | | 652K| 14M| | 1150 | | | Q1,06 | PCWP | |
| 31 | HASH JOIN | | 652K| 14M| | 128 | | | Q1,06 | PCWP | |
| 32 | BUFFER SORT | | | | | | | | Q1,06 | PCWC | |
| 33 | PX RECEIVE | | 1131 | 6786 | | 8 | | | Q1,06 | PCWP | |
| 34 | PX SEND HASH | :TQ10000 | 1131 | 6786 | | 8 | | | | S->P | HASH |
| 35 | TABLE ACCESS FULL | ORG_LOC_DM | 1131 | 6786 | | 8 | | | | | |
| 36 | PX RECEIVE | | 652K| 10M| | 118 | | | Q1,06 | PCWP | |
| 37 | PX SEND HASH | :TQ10003 | 652K| 10M| | 118 | | | Q1,03 | P->P | HASH |
| 38 | PX BLOCK ITERATOR | | 652K| 10M| | 118 | 60 | 60 | Q1,03 | PCWC | |
| 39 | MAT_VIEW ACCESS FULL| INV_MOVE_SKU_LCM_DM | 652K| 10M| | 118 | 60 | 60 | Q1,03 | PCWP | |
| 40 | PARTITION RANGE SINGLE | | 1 | 17 | | 8609 | 59 | 59 | Q1,08 | PCWP | |
| 41 | TABLE ACCESS FULL | SURT_SKU_LCM_DM | 1 | 17 | | 8609 | 59 | 59 | Q1,08 | PCWP | |
| 42 | NESTED LOOPS | | 1 | 16 | | 6 | | | | | |
| 43 | TABLE ACCESS FULL | MAINT_LOAD_DT | 1 | 8 | | 1 | | | | | |
| 44 | INDEX RANGE SCAN | DAY_IDNT_I1 | 1 | 8 | | 5 | | | | | |
Note
- 'PLAN_TABLE' is old version
- cpu costing is off (consider enabling it) -
This is my first pl/sql program, I've written psudocode on paper, but not sure what to do for two parts.
What I'm trying to do is write pl/sql that will check a row based on an employee id #.
declare
cursor cur is
select *
from employee
where employee_id = foo;What we are checking are the results the employee answered. They have answered 180 questions and I want to find when the answer a 0, 7, and 9.
Basically the pl/sql has to loop thru the 180 questions
loop
v_count := vcount + 1
select *
from employee
where q1 thru q180 in (0, 7, 9);
end loop;
dbms_output.put_line ('Employee ID' || employee_id);
dbms_output.put_line ('Q1 - Q180' || q1 - q180); I'm not sure how to write the pl/sql to loop thur all 180 questions.
I'm not sure how to display the output to show what question they scored a 0, 7, and/or a 9 on.
thanks
Message was edited by:
cmmiller536 columns in one table? Yowsa. Without a normalized table, you are going to need dynamic pl/sql and a messy solution.
I would rethink your design, and come up with something more like so:
employee
questions
employee_responses
So that would you could easily do something like this:
declare
cursor c1 is
select ers.question_id,
que.question_name,
ers.rating
from employee emp,
questions que,
employee_responses ers
where emp.employee_id = ers.employee_id and
que.question_id = ers.question_id and
emp.employee_id = v_employee_id and
ers.rating in (0, 7, 9) and
que.enabled_flag = 'Y';
begin
for r1 in c1 loop
dbms_output.put_line('Question: '||r1.question_name);
dbms_output.put_line('Employee Rated this: '||r1.rating);
end loop;
end;Thats how I would do it - I think you are going down the wrong path. What happens if you need to create a new question or delete one? You constantly have to modify the table. Hope this helps -
Execution plan change when querying count(*)
Hi,
Could any one please help me....
Here are my queries
1. select * from my_vew
2. select count(*) from my_view
Explain plan on the above queries are giving differnt plans. I would like to get the plan for count(*) as exactkly same as query no 1. Even I tried explain plan for the below query, which is also not giving the same plan..
select count(*) from (select * from my_view);
All I am trying to do here is to find the total run time without spending much time on passing the result to the client over a network (I beleive set autotrace traceonly option is also passing the result to the network.. only thing is that traceonly option wont display the results). count(*) query is chaning the plan in many ways such as index scan in place of full_table scan and etc.,
Thanks in advance.
Vasanthwhy you want select count(*) from <table>,cause count(*) did single call neednt arraysize to be big which in turn less
LIO,when less LIO then high throughput which is not the case with select * from <table>,i dont know the internals of count(*)
but there would be some mechanics behind this code which always return with less IO
SQL> conn scott/tiger
Connected.
SQL> column plan_plus_exp format a100
SQL> set linesize 1000
SQL> desc t
Name
A
OBJECT_NAME
SQL> select index_name from user_indexes where lower(table_name)='t'
2 /
no rows selected
SQL> select count(*) from t
2 /
COUNT(*)
23486
SQL> set autotrace traceonly
SQL> select * from t
2 /
23486 rows selected.
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=13 Card=23486 Bytes=681094)
1 0 TABLE ACCESS (FULL) OF 'T' (Cost=13 Card=23486 Bytes=681094)
Statistics
23 recursive calls
0 db block gets
1678 consistent gets
0 physical reads
0 redo size
923712 bytes sent via SQL*Net to client
17714 bytes received via SQL*Net from client
1567 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
23486 rows processed
SQL> select count(*) from t
2 /
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=13 Card=1)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'T' (Cost=13 Card=23486)
Statistics
0 recursive calls
0 db block gets
118 consistent gets
0 physical reads
0 redo size
381 bytes sent via SQL*Net to client
499 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processedyou need to compare boths query result consistent gets as well bytes sent via SQL*Net to client and bytes received via SQL*Net from client.
What yours requirment to get alls record as well as maximum throughput,its not the way to do.Just a clue try to implement bulk collect in this case.
Khurram -
Question for SQL execution plan, strange..
HI, all
We meet a strange problem for a execution plan. First, we have a StoreProc, it runs around less than 20 secs. One day, it runs more than 5 mins (Execution plan 1). I checked all the index (fragmentation is low and Scan density is high), and re-run the update
statistics, but the performance still have no any improvement.
This is very strange for me, why the query becomes slow suddenly on one day (we will know the performance immedidately because it is a daily function, user will report to us if the performance is low, we only got complain today.)?
Finally, we tested in two ways.
1. We run the below update statistic command with one index - "update statistics dbo.PCMS_CARD_TRANS MGM_IDX_PCMS_TRANS_TIME_PROCESSING"
Result: It runs under 20 secs.
2. We create a new index - "MGM_IDX_Test_TRANS_TIME"
Result: It runs around 1 second, but I checked the execution plan (Execution plan 2) didn't change and the new index is not use for it...we feel strange again on it......
All information was included in below:
Table - PCMS_CARD_TRANS, PCMS_CARD_PROFILE.
VIEW - PCMS_V_CR_CARD_STOCK
StoreProc: PCMS_CardRoom_GetProcessedCardStock
Index: All zipped.USE [PCMS]
GO
/****** Object: View [dbo].[PCMS_V_CR_CARD_STOCK] Script Date: 4/9/2014 4:30:54 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[PCMS_V_CR_CARD_STOCK]
AS
SELECT dbo.PCMS_CARD_PROFILE.CARD_ID, dbo.PCMS_CARD_PROFILE.TYPE_CODE, dbo.PCMS_CARD_PROFILE.COLOR_SET_CODE,
dbo.PCMS_CARD_PROFILE.VENDOR_ID, dbo.PCMS_CARD_PROFILE.CARD_STATUS, dbo.PCMS_CARD_PROFILE.LOC, dbo.PCMS_CARD_PROFILE.LOC_ID,
dbo.PCMS_CARD_PROFILE.LAST_TRANS_NO, dbo.PCMS_CARD_COLOR_SET_MASTER.COLOR_SET_DESC, dbo.PCMS_CARD_TYPE.TYPE_DESC,
dbo.PCMS_CARD_PROFILE.DECK_AMOUNT, dbo.PCMS_CARD_PROFILE.USAGE_TYPE, dbo.PCMS_CARD_PROFILE.STORAGE_ID,
dbo.PCMS_CARD_PROFILE.STORAGE, dbo.PCMS_CARD_TYPE.CARD_TYPE_GROUP
FROM dbo.PCMS_CARD_PROFILE INNER JOIN
dbo.PCMS_CARD_COLOR_SET_MASTER ON
dbo.PCMS_CARD_PROFILE.COLOR_SET_CODE = dbo.PCMS_CARD_COLOR_SET_MASTER.COLOR_SET_CODE INNER JOIN
dbo.PCMS_CARD_TYPE ON dbo.PCMS_CARD_PROFILE.TYPE_CODE = dbo.PCMS_CARD_TYPE.TYPE_CODE
WHERE (dbo.PCMS_CARD_COLOR_SET_MASTER.ENABLED = 1) AND (dbo.PCMS_CARD_TYPE.ENABLED = 1)
GO
EXEC sys.sp_addextendedproperty @name=N'MS_DiagramPane1', @value=N'[0E232FF0-B466-11cf-A24F-00AA00A3EFFF, 1.00]
Begin DesignProperties =
Begin PaneConfigurations =
Begin PaneConfiguration = 0
NumPanes = 4
Configuration = "(H (1[40] 4[20] 2[20] 3) )"
End
Begin PaneConfiguration = 1
NumPanes = 3
Configuration = "(H (1 [50] 4 [25] 3))"
End
Begin PaneConfiguration = 2
NumPanes = 3
Configuration = "(H (1 [50] 2 [25] 3))"
End
Begin PaneConfiguration = 3
NumPanes = 3
Configuration = "(H (4 [30] 2 [40] 3))"
End
Begin PaneConfiguration = 4
NumPanes = 2
Configuration = "(H (1 [56] 3))"
End
Begin PaneConfiguration = 5
NumPanes = 2
Configuration = "(H (2 [66] 3))"
End
Begin PaneConfiguration = 6
NumPanes = 2
Configuration = "(H (4 [50] 3))"
End
Begin PaneConfiguration = 7
NumPanes = 1
Configuration = "(V (3))"
End
Begin PaneConfiguration = 8
NumPanes = 3
Configuration = "(H (1[56] 4[18] 2) )"
End
Begin PaneConfiguration = 9
NumPanes = 2
Configuration = "(H (1 [75] 4))"
End
Begin PaneConfiguration = 10
NumPanes = 2
Configuration = "(H (1[66] 2) )"
End
Begin PaneConfiguration = 11
NumPanes = 2
Configuration = "(H (4 [60] 2))"
End
Begin PaneConfiguration = 12
NumPanes = 1
Configuration = "(H (1) )"
End
Begin PaneConfiguration = 13
NumPanes = 1
Configuration = "(V (4))"
End
Begin PaneConfiguration = 14
NumPanes = 1
Configuration = "(V (2))"
End
ActivePaneConfig = 0
End
Begin DiagramPane =
Begin Origin =
Top = 0
Left = 0
End
Begin Tables =
Begin Table = "PCMS_CARD_PROFILE"
Begin Extent =
Top = 6
Left = 38
Bottom = 265
Right = 212
End
DisplayFlags = 280
TopColumn = 0
End
Begin Table = "PCMS_CARD_COLOR_SET_MASTER"
Begin Extent =
Top = 6
Left = 250
Bottom = 121
Right = 426
End
DisplayFlags = 280
TopColumn = 0
End
Begin Table = "PCMS_CARD_TYPE"
Begin Extent =
Top = 6
Left = 464
Bottom = 121
Right = 637
End
DisplayFlags = 280
TopColumn = 0
End
End
End
Begin SQLPane =
End
Begin DataPane =
Begin ParameterDefaults = ""
End
Begin ColumnWidths = 13
Width = 284
Width = 1500
Width = 1500
Width = 1500
Width = 1500
Width = 1500
Width = 1500
Width = 1500
Width = 1500
Width = 1500
Width = 1500
Width = 1500
Width = 1500
End
End
Begin CriteriaPane =
Begin ColumnWidths = 11
Column = 1440
Alias = 900
Table = 1170
Output = 720
Append = 1400
NewValue = 1170
SortType = 1350
SortOrder = 1410
GroupBy = 1350
Filter = 1350
Or = 1350
Or = 1350
Or = 1350
End
End
End
' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'VIEW',@level1name=N'PCMS_V_CR_CARD_STOCK'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_DiagramPaneCount', @value=1 , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'VIEW',@level1name=N'PCMS_V_CR_CARD_STOCK'
GO
USE [PCMS]
GO
/****** Object: Index [IDX_PCMS_CARD_PROFILE_LOC] Script Date: 4/9/2014 4:39:51 PM ******/
CREATE NONCLUSTERED INDEX [IDX_PCMS_CARD_PROFILE_LOC] ON [dbo].[PCMS_CARD_PROFILE]
[LOC] ASC,
[LOC_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
GO
USE [PCMS]
GO
/****** Object: Index [IDX_PCMS_CARD_PROFILE_LOC_USAGE] Script Date: 4/9/2014 4:39:56 PM ******/
CREATE NONCLUSTERED INDEX [IDX_PCMS_CARD_PROFILE_LOC_USAGE] ON [dbo].[PCMS_CARD_PROFILE]
[LOC] ASC,
[USAGE_TYPE] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
GO
USE [PCMS]
GO
/****** Object: Index [IDX_PCMS_CARD_PROFILE_STORAGE] Script Date: 4/9/2014 4:40:01 PM ******/
CREATE NONCLUSTERED INDEX [IDX_PCMS_CARD_PROFILE_STORAGE] ON [dbo].[PCMS_CARD_PROFILE]
[STORAGE] ASC,
[STORAGE_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
GO
USE [PCMS]
GO
/****** Object: Index [MGM_IDX_PCMS_CARD_PROFILE_CARD_ID] Script Date: 4/9/2014 4:40:07 PM ******/
CREATE NONCLUSTERED INDEX [MGM_IDX_PCMS_CARD_PROFILE_CARD_ID] ON [dbo].[PCMS_CARD_PROFILE]
[CARD_ID] ASC,
[STORAGE] ASC,
[CARD_STATUS] ASC,
[LOC] ASC
INCLUDE ( [TYPE_CODE],
[COLOR_SET_CODE],
[LOC_ID]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
USE [PCMS]
GO
/****** Object: Index [MGM_IDX_PCMS_CARD_PROFILE_CARD_STATUS] Script Date: 4/9/2014 4:40:12 PM ******/
CREATE NONCLUSTERED INDEX [MGM_IDX_PCMS_CARD_PROFILE_CARD_STATUS] ON [dbo].[PCMS_CARD_PROFILE]
[CARD_STATUS] ASC,
[VENDOR_ID] ASC,
[LOC] ASC
INCLUDE ( [CARD_ID],
[TYPE_CODE],
[COLOR_SET_CODE],
[USAGE_TYPE],
[DECK_AMOUNT],
[LAST_TRANS_NO]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
USE [PCMS]
GO
/****** Object: Index [PK_PCMS_CARD_PROFILE] Script Date: 4/9/2014 4:40:18 PM ******/
ALTER TABLE [dbo].[PCMS_CARD_PROFILE] ADD CONSTRAINT [PK_PCMS_CARD_PROFILE] PRIMARY KEY CLUSTERED
[CARD_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
GO -
What to look for in Execution plans ?
Hi Pals,
Assuming the query execution is slow , I have collected the xml plan. What should I look for in the actual execution plan . What are the top 10 things I need to watch out for?
I know this is a broad and generic question but I am looking for anyone who is experienced in query tuning to answer this question.
Thanks in Advance.Reading execution plans is a bit of an art. But a couple of things:
1) Download and install SQL Sentry Plan Explorer (www.sqlsentry.net). This is a free tool that in msny cases gives a better experience to look at execution plans, particularly big and ugly ones.
2) I usually look for the thickest arrows, as thickness indicates the number of rows being processed.
3) Look for deviations between estimates and actual values, as these deviations are often the source for bad performance. In Plan Explorer, you can quickly flip between the too. In SSMS you need to look at the popup for every operator. (But again, it is
the operator with fat arrows that are of most interest - and those before them.
4) The way to read the plan is that the left-most operator asks the operators it is connected to for data. The net effect is that data flows from right to left, and the right-hand side if often more interesting.
5) Don't pay much attention to the percentages about operator cost. These percentages are estimates only,
not actual values. They are only reliable if the estimates are correct all the way through - and when you have a bad plan that is rarely the case.
This was the overall advice. Then there is more specific one: are indexes being used when expected? Note that scans are necessarily not bad. Sometimes your problem is that you have a loop join + index seek, when you should have had two scans and a hash join.
Try to get a grip of how you would process the query, if you had to do it manually. Does the plan match that idea?
Erland Sommarskog, SQL Server MVP, [email protected] -
Out of the box execution plan for Payables EBS 11.5.10
Has anyone else experienced performance issues with the out of the box execution plan for the Payables subject area for Oracle EBS 11.5.10? Our incremental ETL for this particular subject area is taking 8+ hours. I understand that there are several factors involved with performance and that there are a lot of AP transactions, but this is ridiculous for a nightly incremental ETL job.
In particular it is the SDE_ORA_APTransactionFact_Payment task that is taking forever. This query appears to have extremely high cost (see explain plan below). Has anyone been successful in rewriting or changing this query?
SELECT STATEMENT ALL_ROWSCost: 586,953 Bytes: 16,550 Cardinality: 50
13 NESTED LOOPS OUTER Cost: 586,953 Bytes: 16,550 Cardinality: 50
10 NESTED LOOPS Cost: 586,952 Bytes: 15,800 Cardinality: 50
7 HASH JOIN Cost: 468,320 Bytes: 11,693,526 Cardinality: 59,358
5 HASH JOIN Cost: 429,964 Bytes: 9,200,490 Cardinality: 59,358
3 HASH JOIN Cost: 366,009 Bytes: 7,740,544 Cardinality: 60,473
1 TABLE ACCESS FULL TABLE AP.AP_AE_LINES_ALL Cost: 273,240 Bytes: 15,212,604 Cardinality: 230,494
2 TABLE ACCESS FULL TABLE AP.AP_INVOICE_PAYMENTS_ALL Cost: 45,211 Bytes: 715,512,860 Cardinality: 11,540,530
4 TABLE ACCESS FULL TABLE AP.AP_PAYMENT_SCHEDULES_ALL Cost: 39,003 Bytes: 309,648,420 Cardinality: 11,468,460
6 TABLE ACCESS FULL TABLE AP.AP_CHECKS_ALL Cost: 28,675 Bytes: 130,126,920 Cardinality: 3,098,260
9 TABLE ACCESS BY INDEX ROWID TABLE AP.AP_INVOICES_ALL Cost: 2 Bytes: 119 Cardinality: 1
8 INDEX UNIQUE SCAN INDEX (UNIQUE) AP.AP_INVOICES_U1 Cost: 1 Cardinality: 1
12 TABLE ACCESS BY INDEX ROWID TABLE PO.PO_HEADERS_ALL Cost: 1 Bytes: 15 Cardinality: 1
11 INDEX UNIQUE SCAN INDEX (UNIQUE) PO.PO_HEADERS_U1 Cost: 1 Cardinality: 1Hi Srini, All,
Thanks for the reply.
The payables documentation (i.e. User Guide) discusses about options that could be used in implementing EFT. However, if possible, we would like suggestions on what would be the better ways to implement EFT (US bank) using either XML or text formats. We would also prefer not using e-commerce gateway or EDI.
Thanks in advance.
MM -
Multiple Executions Plans for the same SQL statement
Dear experts,
awrsqrpt.sql is showing multiple executions plans for a single SQL statement. How is it possible that one SQL statement will have multiple Executions Plans within the same AWR report.
Below is the awrsqrpt's output for your reference.
WORKLOAD REPOSITORY SQL Report
Snapshot Period Summary
DB Name DB Id Instance Inst Num Release RAC Host
TESTDB 2157605839 TESTDB1 1 10.2.0.3.0 YES testhost1
Snap Id Snap Time Sessions Curs/Sess
Begin Snap: 32541 11-Oct-08 21:00:13 248 141.1
End Snap: 32542 11-Oct-08 21:15:06 245 143.4
Elapsed: 14.88 (mins)
DB Time: 12.18 (mins)
SQL Summary DB/Inst: TESTDB/TESTDB1 Snaps: 32541-32542
Elapsed
SQL Id Time (ms)
51szt7b736bmg 25,131
Module: SQL*Plus
UPDATE TEST SET TEST_TRN_DAY_CL = (SELECT (NVL(ACCT_CR_BAL,0) + NVL(ACCT_DR_BAL,
0)) FROM ACCT WHERE ACCT_TRN_DT = (:B1 ) AND TEST_ACC_NB = ACCT_ACC_NB(+)) WHERE
TEST_BATCH_DT = (:B1 )
SQL ID: 51szt7b736bmg DB/Inst: TESTDB/TESTDB1 Snaps: 32541-32542
-> 1st Capture and Last Capture Snap IDs
refer to Snapshot IDs witin the snapshot range
-> UPDATE TEST SET TEST_TRN_DAY_CL = (SELECT (NVL(ACCT_CR_BAL,0) + NVL(AC...
Plan Hash Total Elapsed 1st Capture Last Capture
# Value Time(ms) Executions Snap ID Snap ID
1 2960830398 25,131 1 32542 32542
2 3834848140 0 0 32542 32542
Plan 1(PHV: 2960830398)
Plan Statistics DB/Inst: TESTDB/TESTDB1 Snaps: 32541-32542
-> % Total DB Time is the Elapsed Time of the SQL statement divided
into the Total Database Time multiplied by 100
Stat Name Statement Per Execution % Snap
Elapsed Time (ms) 25,131 25,130.7 3.4
CPU Time (ms) 23,270 23,270.2 3.9
Executions 1 N/A N/A
Buffer Gets 2,626,166 2,626,166.0 14.6
Disk Reads 305 305.0 0.3
Parse Calls 1 1.0 0.0
Rows 371,735 371,735.0 N/A
User I/O Wait Time (ms) 564 N/A N/A
Cluster Wait Time (ms) 0 N/A N/A
Application Wait Time (ms) 0 N/A N/A
Concurrency Wait Time (ms) 0 N/A N/A
Invalidations 0 N/A N/A
Version Count 2 N/A N/A
Sharable Mem(KB) 26 N/A N/A
Execution Plan
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | UPDATE STATEMENT | | | | 1110 (100)| |
| 1 | UPDATE | TEST | | | | |
| 2 | TABLE ACCESS FULL | TEST | 116K| 2740K| 1110 (2)| 00:00:14 |
| 3 | TABLE ACCESS BY INDEX ROWID| ACCT | 1 | 26 | 5 (0)| 00:00:01 |
| 4 | INDEX RANGE SCAN | ACCT_DT_ACC_IDX | 1 | | 4 (0)| 00:00:01 |
Plan 2(PHV: 3834848140)
Plan Statistics DB/Inst: TESTDB/TESTDB1 Snaps: 32541-32542
-> % Total DB Time is the Elapsed Time of the SQL statement divided
into the Total Database Time multiplied by 100
Stat Name Statement Per Execution % Snap
Elapsed Time (ms) 0 N/A 0.0
CPU Time (ms) 0 N/A 0.0
Executions 0 N/A N/A
Buffer Gets 0 N/A 0.0
Disk Reads 0 N/A 0.0
Parse Calls 0 N/A 0.0
Rows 0 N/A N/A
User I/O Wait Time (ms) 0 N/A N/A
Cluster Wait Time (ms) 0 N/A N/A
Application Wait Time (ms) 0 N/A N/A
Concurrency Wait Time (ms) 0 N/A N/A
Invalidations 0 N/A N/A
Version Count 2 N/A N/A
Sharable Mem(KB) 26 N/A N/A
Execution Plan
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | UPDATE STATEMENT | | | | 2 (100)| |
| 1 | UPDATE | TEST | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 28 | 2 (0)| 00:00:01 |
| 3 | INDEX RANGE SCAN | TEST_DT_IND | 1 | | 1 (0)| 00:00:01 |
| 4 | TABLE ACCESS BY INDEX ROWID| ACCT | 1 | 26 | 4 (0)| 00:00:01 |
| 5 | INDEX RANGE SCAN | INDX_ACCT_DT | 1 | | 3 (0)| 00:00:01 |
Full SQL Text
SQL ID SQL Text
51szt7b736bm UPDATE TEST SET TEST_TRN_DAY_CL = (SELECT (NVL(ACCT_CR_BAL, 0) +
NVL(ACCT_DR_BAL, 0)) FROM ACCT WHERE ACCT_TRN_DT = (:B1 ) AND PB
RN_ACC_NB = ACCT_ACC_NB(+)) WHERE TEST_BATCH_DT = (:B1 )Your input is highly appreciated.
Thanks for taking your time in answering my question.
RegardsOracle Lover3 wrote:
Dear experts,
awrsqrpt.sql is showing multiple executions plans for a single SQL statement. How is it possible that one SQL statement will have multiple Executions Plans within the same AWR report.If you're using bind variables and you've histograms on your columns which can be created by default in 10g due to the "SIZE AUTO" default "method_opt" parameter of DBMS_STATS.GATHER__STATS it is quite normal that you get different execution plans for the same SQL statement. Depending on the values passed when the statement is hard parsed (this feature is called "bind variable peeking" and enabled by default since 9i) an execution plan is determined and re-used for all further executions of the same "shared" SQL statement.
If now your statement ages out of the shared pool or is invalidated due to some DDL or statistics gathering activity it will be re-parsed and again the values passed in that particular moment will determine the execution plan. If you have skewed data distribution and a histogram in place that reflects that skewness you might get different execution plans depending on the actual values used.
Since this "flip-flop" behaviour can sometimes be counter-productive if you're unlucky and the values used to hard parse the statement leading to a plan that is unsuitable for the majority of values used afterwards, 11g introduced the "adaptive" cursor sharing that attempts to detect such a situation and can automatically re-evaluate the execution plan of the statement.
Regards,
Randolf
Oracle related stuff blog:
http://oracle-randolf.blogspot.com/
SQLTools++ for Oracle (Open source Oracle GUI for Windows):
http://www.sqltools-plusplus.org:7676/
http://sourceforge.net/projects/sqlt-pp/ -
How can I get an execution plan for a Function in oracle 10g
Hi
I have:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
PL/SQL Release 10.2.0.4.0 - Production
CORE 10.2.0.4.0 Production
TNS for Solaris: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production
I would like to know if is possible to get an EXECUTION PLAN for a FUNCTION if so, how can I get it ?
RegardsYou can query the AWR data if your interesting SQL consumes enough resources.
Here is a SQL*Plus script I call MostCPUIntensiveSQLDuringInterval.sql (nice name eh?)
You'll need to know the AWR snap_id numbers for the time period of interest, then run it like this to show the top 20 SQLs during the interval:
@MostCPUIntensiveSQLDuringInterval 20The script outputs a statement to run when you are interested in looking at the plan for an interesting looking statement.
-- MostCPUintesticeSQLDuringInterval: Report on the top n SQL statements during an AWR snapshot interval.
-- The top statements are ranked by CPU usage
col inst_no format 999 heading 'RAC|Node'
col sql_id format a16 heading 'SQL_ID'
col plan_hash_value format 999999999999 heading 'Plan|hash_value'
col parsing_schema_name format a12 heading 'Parsing|Schema'
col module format a10 heading 'Module'
col pct_of_total format 999.99 heading '% Total'
col cpu_time format 999,999,999 heading 'CPU |Time (ms)'
col elapsed_time format 999,999,999 heading 'Elapsed |Time (ms)'
col lios format 9,999,999,999 heading 'Logical|Reads'
col pios format 999,999,999 heading 'Physical|Reads'
col execs format 99,999,999 heading 'Executions'
col fetches format 99,999,999 heading 'Fetches'
col sorts format 999,999 heading 'Sorts'
col parse_calls format 999,999 heading 'Parse|Calls'
col rows_processed format 999,999,999 heading 'Rows|Processed'
col iowaits format 999,999,999,999 heading 'iowaits'
set lines 195
set pages 75
PROMPT Top &&1 SQL statements during interval
SELECT diff.*
FROM (SELECT e.instance_number inst_no
,e.sql_id
,e.plan_hash_value
,e.parsing_schema_name
,substr(trim(e.module),1,10) module
,ratio_to_report(e.cpu_time_total - b.cpu_time_total) over (partition by 1) * 100 pct_of_total
,(e.cpu_time_total - b.cpu_time_total)/1000 cpu_time
,(e.elapsed_time_total - b.elapsed_time_total)/1000 elapsed_time
,e.buffer_gets_total - b.buffer_gets_total lios
,e.disk_reads_total - b.disk_reads_total pios
,e.executions_total - b.executions_total execs
,e.fetches_total - b.fetches_total fetches
,e.sorts_total - b.sorts_total sorts
,e.parse_calls_total - b.parse_calls_total parse_calls
,e.rows_processed_total - b.rows_processed_total rows_processed
-- ,e.iowait_total - b.iowait_total iowaits
-- ,e.plsexec_time_total - b.plsexec_time_total plsql_time
FROM dba_hist_sqlstat b -- begining snap
,dba_hist_sqlstat e -- ending snap
WHERE b.sql_id = e.sql_id
AND b.dbid = e.dbid
AND b.instance_number = e.instance_number
and b.plan_hash_value = e.plan_hash_value
AND b.snap_id = &LowSnapID
AND e.snap_id = &HighSnapID
ORDER BY e.cpu_time_total - b.cpu_time_total DESC
) diff
WHERE ROWNUM <=&&1
set define off
prompt to get the text of the SQL run the following:
prompt @id2sql &SQL_id
prompt .
prompt to obtain the execution plan for a session run the following:
prompt select * from table(DBMS_XPLAN.DISPLAY_AWR('&SQL_ID'));
prompt or
prompt select * from table(DBMS_XPLAN.DISPLAY_AWR('&SQL_ID',NULL,NULL,'ALL'));
prompt .
set define on
undefine LowSnapID
undefine HighSnapIDI guess you'll need the companion script id2sql.sql, so here it is:
set lines 190
set verify off
declare
maxDisplayLine NUMBER := 150; --max linesize to display the SQL
WorkingLine VARCHAR2(32000);
CurrentLine VARCHAR2(64);
LineBreak NUMBER;
cursor ddl_cur is
select sql_id
,sql_text
from v$sqltext_with_newlines
where sql_id='&1'
order by piece
ddlRec ddl_cur%ROWTYPE;
begin
WorkingLine :='.';
OPEN ddl_cur;
LOOP
FETCH ddl_cur INTO ddlRec;
EXIT WHEN ddl_cur%NOTFOUND;
IF ddl_cur%ROWCOUNT = 1 THEN
dbms_output.put_line('.');
dbms_output.put_line(' sql_id: '||ddlRec.sql_id);
dbms_output.put_line('.');
dbms_output.put_line('.');
dbms_output.put_line('SQL Text');
dbms_output.put_line('----------------------------------------------------------------');
END IF;
CurrentLine := ddlRec.sql_text;
WHILE LENGTH(CurrentLine) > 1 LOOP
IF INSTR(CurrentLine,CHR(10)) > 0 THEN -- if the current line has an embeded newline
WorkingLine := WorkingLine||SUBSTR(CurrentLine,1,INSTR(CurrentLine,CHR(10))-1); -- append up to new line
CurrentLine := SUBSTR(CurrentLine,INSTR(CurrentLine,CHR(10))+1); -- strip off up through new line character
dbms_output.put_line(WorkingLine); -- print the WorkingLine
WorkingLine :=''; -- reset the working line
ELSE
WorkingLine := WorkingLine||CurrentLine; -- append the current line
CurrentLine :=''; -- the rest of the line has been processed
IF LENGTH(WorkingLine) > maxDisplayLine THEN -- the line is morethan the display limit
LineBreak := instr(substr(WorkingLine,1,maxDisplayLine),' ',-1); --find the last space before the display limit
IF LineBreak = 0 THEN -- there is no space, so look for a comma instead
LineBreak := substr(WorkingLine,instr(substr(WorkingLine,1,maxDisplayLine),',',-1));
END IF;
IF LineBreak = 0 THEN -- no space or comma, so force the line break at maxDisplayLine
LineBreak := maxDisplayLine;
END IF;
dbms_output.put_line(substr(WorkingLine,1,LineBreak));
WorkingLine:=substr(WorkingLine,LineBreak);
END IF;
END IF;
END LOOP;
--dbms_output.put(ddlRec.sql_text);
END LOOP;
dbms_output.put_line(WorkingLine);
dbms_output.put_line('----------------------------------------------------------------');
CLOSE ddl_cur;
END;
/ -
Too many nested loops in execution plan?
Hi,
i wonder about execution plan not indicating that access to some tables (for join) is in parallel.
Please see this example:
------------------------ snip ------------------------------------
drop table test_a1;
drop table test_a2;
drop table test_b;
drop table test_c;
drop table test_d;
create table test_a1 (
x number,
y number,
z number);
create unique index testa1_pk on test_a1 (x);
create table test_a2 (
x number,
y number,
z number);
create unique index testa2_pk on test_a2 (x);
create table test_b (
x number,
y number,
z number);
create unique index testb_pk on test_b (y);
create table test_c (
x number,
y number,
z number);
create unique index testc_pk on test_b (z);
create table test_d (
x number,
y number,
z number);
create unique index testd_pk on test_d (y);
select
a1.x a1_x,
a1.y a1_y,
a1.z a1_z,
a2.x a2_x,
a2.y a2_y,
a2.z a2_z,
b.x b_x,
b.y b_y,
b.z b_z,
c.x c_x,
c.y c_y,
c.z c_z,
d.x d_x,
d.y d_y,
d.z d_z
from test_a1 a1, test_a2 a2, test_b b, test_c c, test_d d
where a1.x = 100
and a2.x = 200
and b.y = a1.y
and c.z = b.z
and d.y = a1.y;
------------------------ snap ------------------------------------
The execution plan goes like this:
Select Stmt
nested loops
nested loops
nested loops
nested loops
table access
index
access predicate
a2.x = 200
table access
index
access predicate
a1.x = 100
table access
index
access predicate
d.y = a1.y
table access
index
access predicate
b.y = a1.y
table acess
index
acess predicate
c.z = b.z
Access to tables a1 and a2 is on the same level (in parallel - i guess).
However, why isn't access to table d and b on the same level?
Both depend on a1. So no need to execute one after the other (no inter-dependency).
Maybe i have just wrong expectation to the output of the execution plan(?!)
- many thanks!
best regards,
FrankPreservation of identation and spacing is invaluable when it comes to reading an explain plan.
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 195 | 2 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 1 | 195 | 2 (0)| 00:00:01 |
| 2 | NESTED LOOPS | | 1 | 156 | 0 (0)| 00:00:01 |
| 3 | NESTED LOOPS | | 1 | 117 | 0 (0)| 00:00:01 |
| 4 | NESTED LOOPS | | 1 | 78 | 0 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| TEST_A2 | 1 | 39 | 0 (0)| 00:00:01 |
|* 6 | INDEX UNIQUE SCAN | TESTA2_PK | 1 | | 0 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID| TEST_A1 | 1 | 39 | 0 (0)| 00:00:01 |
|* 8 | INDEX UNIQUE SCAN | TESTA1_PK | 1 | | 0 (0)| 00:00:01 |
| 9 | TABLE ACCESS BY INDEX ROWID | TEST_D | 82 | 3198 | 0 (0)| 00:00:01 |
|* 10 | INDEX UNIQUE SCAN | TESTD_PK | 1 | | 0 (0)| 00:00:01 |
| 11 | TABLE ACCESS BY INDEX ROWID | TEST_B | 82 | 3198 | 0 (0)| 00:00:01 |
|* 12 | INDEX UNIQUE SCAN | TESTB_PK | 1 | | 0 (0)| 00:00:01 |
|* 13 | TABLE ACCESS FULL | TEST_C | 1 | 39 | 2 (0)| 00:00:01 |
Predicate Information (identified by operation id):
6 - access("A2"."X"=200)
8 - access("A1"."X"=100)
10 - access("D"."Y"="A1"."Y")
12 - access("B"."Y"="A1"."Y")
13 - filter("C"."Z"="B"."Z")
Access to tables a1 and a2 is on the same level (in parallel - i guess).
Maybe i have just wrong expectation to the output of the execution plan(?!)You guess wrong, there's nothing parallel going on here.
Execution plan is a tree of parent-child operations.
For example, the NESTED LOOP at operation 4 has two children @ 5 and 7.
Both of these operations- 5 & 7 - have a single child operation.
The execution tree starts with operation 6, using the TESTA2_PK index to identify rows where A2.X=100.
From this list of rowids, we go to the table TEST_A2 operation 5.
The rows from operation five feed into the NESTED LOOP - operation 4.
For each of these rows, we go to TEST_A1 via the index TEST_A1_PK for rows where A1.X=100.
This is really a cartesian join because there's no join condition between the two tables.
etc, etc, etc
Three things in particular to point out.
Firstly, that nothing joins to A2. So there will be a cartesian product - i.e. for every row in the result set between the joined tables A1, B, C and D, these will be multiplied by the number of rows returned by the the A2 rowsource.
Secondly, when everything has got one or zero rows (or the optimizer thinks that it's one or zero rows), you can get very different plans from when there are known/thought to be more rows.
Both depend on a1. So no need to execute one after the other (no inter-dependency).Thirdly, in terms of isolated join operations (ignoring A2 and C for the moment), A1 cannot join to B and D at the same time, you can either join A1 to B and then join the result of that to D, or join A1 to D then B, which is what you've got in your plan (well, actually we have A2 joined to A1 then the result of that joined to D and then the result of that to B).
Edited by: Dom Brooks on Jul 6, 2011 4:07 PM
Corrected typo -
Several nested loop at the same level in an execution plan
Hi, I am using 11gR2, and I've seen a execution plan in the trace of my SQL query (also shown in pl/sql explain plan) with 4 nested loops all at the same level, what does this mean?
i.e.
- SELECT STATEMENT, GOAL = FIRST_ROWS
+ NESTED LOOPS
+ NESTED LOOPS
+ NESTED LOOPS
+ NESTED LOOPS
each NESTED LOOP can be expanded to 2 further actions, which make sense to me. e.g.
+ NESTED LOOPS
+ TABLE ACCESS BY INDEX ROWID
+ TABLE ACCESS BY INDEX ROWID
THANKS
Ye>
why there are 4 Nested Loops
what is the final result set for the SELECT statement come from (any one of the 4)
the query run so slow in 11R2
>
So far you are the only one who knows what the query and execution plan are because you haven't posted them
>
Then you need to post the query, tell us what indexes are on the join columns and post the complete plan.
>
We can't even begin to explain why Oracle might have chosen the plan it did if we can't see the query and plan you want explained.
And if we only see the plan we might be able to tell you what Oracle is doing but without knowing what indexes might be on the join columns and the filter criteria columns we can't tell you why Oracle chose the plan it chose.
And the excerpt of the plan you did provide is incomplete. You removed the indenting possibly because you did not enclose it in 'code' tags (see the FAQ).
>
- SELECT STATEMENT, GOAL = FIRST_ROWS
+ NESTED LOOPS
+ NESTED LOOPS
+ NESTED LOOPS
+ NESTED LOOPS
>
There can't be four nested loops like that at the top level since the top level will be combining the result sets from it's children. A nested loop will have two children; like the last part you showed:
>
+ NESTED LOOPS
+ TABLE ACCESS BY INDEX ROWID
+ TABLE ACCESS BY INDEX ROWID
>
The two 'TABLE ACCESS ...' will be indented on a normal plan.
Without the query and plan there isn't much we can tell you. -
Tkprof not showing the Execution Plan for Statement
Hi all
using oracle 9i release 2
I have issued the following statements
alter session set sql_trace
alter session set events '10046 trace name context forever, level 12';
--then executed a pl-sql procedure
after reading the traceout outfile it shows the Execution plan for statements directly wirtten under begin and end block and doesnot displays the plan for the statements written like this
procedure a is
cursor b is
select ename,dname from dept a,emp b
where a.deptno=b.deptno;
begin
for x in a loop --plan not found but stats are written
select ename into v_ename from emp where empno=300; --does show the plan+stats
end;
what I am missing to get the actual plan in trace output file
thanks in advanceYou have to exit sql*plus after running the procedure, example tkprof is below:
declare
cursor c is
select ename, dname
from emp, dept
where emp.deptno = dept.deptno;
begin
for v_x in c
loop
dbms_output.put_line(v_x.ename || ' ' ||v_x.dname);
end loop;
end;
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.06 0 0 0 1
Fetch 0 0.00 0.00 0 0 0 0
total 2 0.00 0.06 0 0 0 1
Misses in library cache during parse: 0
Optimizer goal: CHOOSE
Parsing user id: 68
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 1 0.00 0.00
SQL*Net message from client 1 0.00 0.00
SELECT ENAME, DNAME
FROM
EMP, DEPT WHERE EMP.DEPTNO = DEPT.DEPTNO
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 15 0.01 0.00 0 44 0 14
total 17 0.01 0.00 0 44 0 14
Misses in library cache during parse: 0
Optimizer goal: CHOOSE
Parsing user id: 68 (recursive depth: 1)
Rows Row Source Operation
14 NESTED LOOPS
14 TABLE ACCESS FULL EMP
14 TABLE ACCESS BY INDEX ROWID DEPT
14 INDEX UNIQUE SCAN DEPT_PK (object id 40350)
Best Regards
Krystian Zieja / mob -
SQL - Need Tunning tips for group by [LATEST EXECUTION PLAN IS ATTACHED]
Hi All Experts,
My SQL is taking so much time to execute. If I remove the group by clause it is running within a minute but as soon as I am putting sum() and group by clause it is taking ages to run the sql. Number of records are wihout group by clause is almost 85 Lachs (8 Million). Is hugh dataset is killing this? Is there any way to tune the data on Group by clause. Below is my Select hints and execution plan. Please help.
SQL
SELECT /*+ CURSOR_SHARING_EXACT gather_plan_statistics all_rows no_index(atm) no_expand
leading (src cpty atm)
index(bk WBKS_PK) index(src WSRC_UK1) index(acct WACC_UK1)
use_nl(acct src ccy prd cpty grate sb) */
EXECUTION PLAN
PLAN_TABLE_OUTPUT
SQL_ID 1y5pdhnb9tks5, child number 0
SELECT /*+ CURSOR_SHARING_EXACT gather_plan_statistics all_rows no_index(atm) no_expand leading (src cpty atm) index(bk
WBKS_PK) index(src WSRC_UK1) index(acct WACC_UK1) use_nl(acct src ccy prd cpty grate sb) */ atm.business_date,
atm.entity legal_entity, TO_NUMBER (atm.set_of_books) setofbooksid, atm.source_system_id sourcesystemid,
ccy.ccy_currency_code ccy_currency_code, acct.acct_account_code, 0 gl_bal, SUM (atm.amount)
atm_bal, 0 gbp_equ, ROUND (SUM (atm.amount * grate.rate), 4) AS
atm_equ, prd.prd_product_code, glacct.parentreportingclassification parentreportingclassification,
cpty_counterparty_code FROM wh_sources_d src,
Plan hash value: 4193892926
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem |
| 1 | HASH GROUP BY | | 1 | 1 | 471 |00:31:38.26 | 904M| 76703 | 649K| 649K| 1149K (0)|
| 2 | NESTED LOOPS | | 1 | 1 | 8362K|00:47:06.06 | 904M| 76703 | | | |
| 3 | NESTED LOOPS | | 1 | 1 | 10M|00:28:48.84 | 870M| 17085 | | | |
| 4 | NESTED LOOPS | | 1 | 1 | 10M|00:27:56.05 | 849M| 17084 | | | |
| 5 | NESTED LOOPS | | 1 | 8 | 18M|00:14:10.93 | 246M| 17084 | | | |
| 6 | NESTED LOOPS | | 1 | 22 | 18M|00:11:58.96 | 189M| 17084 | | | |
| 7 | NESTED LOOPS | | 1 | 22 | 18M|00:10:24.69 | 152M| 17084 | | | |
| 8 | NESTED LOOPS | | 1 | 1337 | 18M|00:06:00.74 | 95M| 17083 | | | |
| 9 | NESTED LOOPS | | 1 | 1337 | 18M|00:02:52.20 | 38M| 17073 | | | |
|* 10 | HASH JOIN | | 1 | 185K| 18M|00:03:46.38 | 1177K| 17073 | 939K| 939K| 575K (0)|
| 11 | NESTED LOOPS | | 1 | 3 | 3 |00:00:00.01 | 11 | 0 | | | |
| 12 | TABLE ACCESS BY INDEX ROWID | WH_SOURCES_D | 1 | 3 | 3 |00:00:00.01 | 3 | 0 | | | |
|* 13 | INDEX RANGE SCAN | WSRC_UK1 | 1 | 3 | 3 |00:00:00.01 | 2 | 0 | | | |
|* 14 | TABLE ACCESS BY INDEX ROWID | WH_COUNTERPARTIES_D | 3 | 1 | 3 |00:00:00.01 | 8 | 0 | | | |
|* 15 | INDEX UNIQUE SCAN | WCPY_U1 | 3 | 1 | 3 |00:00:00.01 | 5 | 0 | | | |
| 16 | PARTITION RANGE SINGLE | | 1 | 91M| 91M|00:00:00.08 | 1177K| 17073 | | | |
|* 17 | TABLE ACCESS FULL | WH_ATM_BALANCES_F | 1 | 91M| 91M|00:00:00.04 | 1177K| 17073 | | | |
|* 18 | TABLE ACCESS BY INDEX ROWID | WH_PRODUCTS_D | 18M| 1 | 18M|00:01:43.88 | 37M| 0 | | | |
|* 19 | INDEX UNIQUE SCAN | WPRD_UK1 | 18M| 1 | 18M|00:00:52.13 | 18M| 0 | | | |
|* 20 | TABLE ACCESS BY GLOBAL INDEX ROWID| WH_BOOKS_D | 18M| 1 | 18M|00:02:53.01 | 56M| 10 | | | |
|* 21 | INDEX UNIQUE SCAN | WBKS_PK | 18M| 1 | 18M|00:01:08.32 | 37M| 10 | | | |
|* 22 | TABLE ACCESS BY INDEX ROWID | T_SDM_SOURCEBOOK | 18M| 1 | 18M|00:03:43.66 | 56M| 1 | | | |
|* 23 | INDEX RANGE SCAN | TSSB_N5 | 18M| 2 | 23M|00:01:11.50 | 18M| 1 | | | |
|* 24 | TABLE ACCESS BY INDEX ROWID | WH_CURRENCIES_D | 18M| 1 | 18M|00:01:51.21 | 37M| 0 | | | |
|* 25 | INDEX UNIQUE SCAN | WCUR_PK | 18M| 1 | 18M|00:00:49.26 | 18M| 0 | | | |
| 26 | TABLE ACCESS BY INDEX ROWID | WH_GL_DAILY_RATES_F | 18M| 1 | 18M|00:01:55.84 | 56M| 0 | | | |
|* 27 | INDEX UNIQUE SCAN | WGDR_U2 | 18M| 1 | 18M|00:01:10.89 | 37M| 0 | | | |
| 28 | INLIST ITERATOR | | 18M| | 10M|00:22:40.03 | 603M| 0 | | | |
|* 29 | TABLE ACCESS BY INDEX ROWID | WH_ACCOUNTS_D | 150M| 1 | 10M|00:20:19.05 | 603M| 0 | | | |
|* 30 | INDEX UNIQUE SCAN | WACC_UK1 | 150M| 5 | 150M|00:10:16.81 | 452M| 0 | | | |
| 31 | TABLE ACCESS BY INDEX ROWID | T_SDM_GLACCOUNT | 10M| 1 | 10M|00:00:50.64 | 21M| 1 | | | |
|* 32 | INDEX UNIQUE SCAN | TSG_PK | 10M| 1 | 10M|00:00:26.17 | 10M| 0 | | | |
|* 33 | TABLE ACCESS BY INDEX ROWID | WH_COMMON_TRADES_D | 10M| 1 | 8362K|00:18:52.56 | 33M| 59618 | | | |
|* 34 | INDEX UNIQUE SCAN | WCTD_PK | 10M| 1 | 10M|00:03:06.56 | 21M| 5391 | | | |
Edited by: user535789 on Mar 17, 2011 9:45 PM
Edited by: user535789 on Mar 20, 2011 8:33 PMuser535789 wrote:
Hi All Experts,
My SQL is taking so much time to execute. If I remove the group by clause it is running within a minute but as soon as I am putting sum() and group by clause it is taking ages to run the sql. Number of records are wihout group by clause is almost 85 Lachs (*8 Million*). Is hugh dataset is killing this? Is there any way to tune the data on Group by clause. Below is my Select hints and execution plan. Please help.I doubt that your 8 million records are shown within minutes.
I guess that the output started after a few minutes. But this does not mean that the full resultset is there. It just means the database is able to return to you the first few records after a few minutes.
Once you add a group by (or an order by) then this requires that all the rows need to be fetched before the database can start showing them to you.
But maybe you could run some tests to compare the full output. I find it useful to SET AUTOTRACE TRACEONLY for such a purpose (in sql plus). This avoids to print the selection on the screen.
Maybe you are looking for
-
NM
-
Backing up an iPad/iPhone and Restoring from Backup
To preface this post, I have always had Apple products and currently own an iPhone, iPad and MacBook Pro. I have also spent about 4 hours on the phone with Apple support staff and they recommended I make a post on the Apple Support Forums. Basically,
-
After uninstalling Muse Creative Cloud is telling me it is still there and up to date. Each time I try to download it I am sent straight back to Adobe Creatice Cloud, and once again telling me it's up to date. How do I reinstall it
-
Tree node selection handler...
Hi i am having a tree of nodes.. I am looking for a functionality where on the click of the tree node ( i.e, on just clicking or selecting the disabled command link ), the af:commandToolbarButton icons on the toolbar are enabled or disabled. Can anyo
-
I use a cad cam software that allows you to create, edit and manage the links on the left hand side of the File>Open window. This is the area that usually contains "My Recent Files" "Desktop" "My Documents" etc. The ability to change and manage the