I ran the execution plan for faster query below is the plan
********************************
SQL_ID 4yx8q19gyg2tw, child number 0
-------------------------------------
SELECT /*+ gather_plan_statistics */ Prh.Segment1 Pr_Num, --tst100
Prh.Description, Prh.Authorization_Status,
Prh.Creation_Date, Prl.Line_Num Pr_Line_Num,
Prl.Unit_Meas_Lookup_Code, Prl.Quantity, Prl.Unit_Price,
Prl.Item_Description, Prl.Line_Location_Id,
Prd.Distribution_Id, glcc.segment2 FROM
Apps.Po_Requisition_Headers_All Prh, Apps.Po_Requisition_Lines_All
Prl, Apps.Po_Req_Distributions_All Prd,
Apps.Gl_Code_Combinations Glcc WHERE Prh.Type_Lookup_Code = 'PURCHASE'
-- AND Prh.Authorization_Status = 'APPROVED' AND
Prh.Requisition_Header_Id = Prl.Requisition_Header_Id AND
Prd.Requisition_Line_Id = Prl.Requisition_Line_Id AND
Glcc.Code_Combination_Id = Prd.Code_Combination_Id AND Glcc.Segment2
IN ('12145', '12155') AND (Glcc.Segment6 ='03271' )
Plan hash value: 2926323738
-----------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads |
-----------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 170 |00:00:04.19 | 83356 | 65713 |
| 1 | NESTED LOOPS | | 1 | 121 | 170 |00:00:04.19 | 83356 | 65713 |
| 2 | NESTED LOOPS | | 1 | 121 | 170 |00:00:03.98 | 83183 | 65606 |
| 3 | NESTED LOOPS | | 1 | 121 | 170 |00:00:03.98 | 82848 | 65511 |
|* 4 | HASH JOIN | | 1 | 121 | 170 |00:00:03.94 | 82338 | 65276 |
| 5 | TABLE ACCESS BY INDEX ROWID BATCHED| GL_CODE_COMBINATIONS | 1 | 2 | 18 |00:00:00.01 | 23 | 3 |
|* 6 | INDEX RANGE SCAN | GL_CODE_COMBINATIONS_CAT | 1 | 2 | 18 |00:00:00.01 | 4 | 3 |
| 7 | TABLE ACCESS FULL | PO_REQ_DISTRIBUTIONS_ALL | 1 | 3185K| 3239K|00:00:02.16 | 82315 | 65273 |
| 8 | TABLE ACCESS BY INDEX ROWID | PO_REQUISITION_LINES_ALL | 170 | 1 | 170 |00:00:00.15 | 510 | 235 |
|* 9 | INDEX UNIQUE SCAN | PO_REQUISITION_LINES_U1 | 170 | 1 | 170 |00:00:00.08 | 338 | 112 |
|* 10 | INDEX UNIQUE SCAN | PO_REQUISITION_HEADERS_U1 | 170 | 1 | 170 |00:00:00.06 | 335 | 95 |
|* 11 | TABLE ACCESS BY INDEX ROWID | PO_REQUISITION_HEADERS_ALL | 170 | 1 | 170 |00:00:00.07 | 173 | 107 |
-----------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("GLCC"."CODE_COMBINATION_ID"="PRD"."CODE_COMBINATION_ID")
6 - access("GLCC"."SEGMENT6"='03271')
filter(("GLCC"."SEGMENT2"='12145' OR "GLCC"."SEGMENT2"='12155'))
9 - access("PRD"."REQUISITION_LINE_ID"="PRL"."REQUISITION_LINE_ID")
10 - access("PRH"."REQUISITION_HEADER_ID"="PRL"."REQUISITION_HEADER_ID")
11 - filter("PRH"."TYPE_LOOKUP_CODE"='PURCHASE')
********************************Then i ran the execution plan for slower query
********************************
SQL_ID 00p1xpq5k4ahw, child number 0
-------------------------------------
SELECT /*+ gather_plan_statistics */ Prh.Segment1 Pr_Num, --tst101
Prh.Description, Prh.Authorization_Status,
Prh.Creation_Date, Prl.Line_Num Pr_Line_Num,
Prl.Unit_Meas_Lookup_Code, Prl.Quantity, Prl.Unit_Price,
Prl.Item_Description, Prl.Line_Location_Id,
Prd.Distribution_Id, glcc.segment2 FROM
Apps.Po_Requisition_Headers_All Prh, Apps.Po_Requisition_Lines_All
Prl, Apps.Po_Req_Distributions_All Prd,
Apps.Gl_Code_Combinations Glcc WHERE Prh.Type_Lookup_Code = 'PURCHASE'
AND Prh.Authorization_Status = 'APPROVED' AND
Prh.Requisition_Header_Id = Prl.Requisition_Header_Id AND
Prd.Requisition_Line_Id = Prl.Requisition_Line_Id AND
Glcc.Code_Combination_Id = Prd.Code_Combination_Id AND Glcc.Segment2
IN ('12145', '12155') AND (Glcc.Segment6 ='03271' )
Plan hash value: 3890956966
-----------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads |
-----------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 165 |00:00:00.73 | 8001K| 372K|
|* 1 | HASH JOIN | | 1 | 15 | 165 |00:00:00.73 | 8001K| 372K|
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED | GL_CODE_COMBINATIONS | 1 | 2 | 18 |00:00:00.01 | 22 | 2 |
|* 3 | INDEX RANGE SCAN | GL_CODE_COMBINATIONS_CAT | 1 | 2 | 18 |00:00:00.01 | 4 | 2 |
| 4 | NESTED LOOPS | | 1 | 401K| 2903K|00:03:23.37 | 8001K| 372K|
| 5 | NESTED LOOPS | | 1 | 401K| 2903K|00:02:43.88 | 6882K| 306K|
| 6 | NESTED LOOPS | | 1 | 397K| 2831K|00:02:28.47 | 3510K| 291K|
|* 7 | TABLE ACCESS BY INDEX ROWID BATCHED| PO_REQUISITION_HEADERS_ALL | 1 | 162K| 1172K|00:00:25.61 | 86462 | 55192 |
|* 8 | INDEX RANGE SCAN | PO_REQUISITION_HEADERS_N3 | 1 | 163K| 1172K|00:00:04.94 | 9042 | 6466 |
| 9 | TABLE ACCESS BY INDEX ROWID BATCHED| PO_REQUISITION_LINES_ALL | 1172K| 2 | 2831K|00:02:11.01 | 3424K| 236K|
|* 10 | INDEX RANGE SCAN | PO_REQUISITION_LINES_U2 | 1172K| 2 | 2831K|00:00:13.60 | 2034K| 16302 |
|* 11 | INDEX RANGE SCAN | PO_REQ_DISTRIBUTIONS_N1 | 2831K| 1 | 2903K|00:00:17.12 | 3371K| 14973 |
| 12 | TABLE ACCESS BY INDEX ROWID | PO_REQ_DISTRIBUTIONS_ALL | 2903K| 1 | 2903K|00:00:37.59 | 1118K| 65871 |
-----------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("GLCC"."CODE_COMBINATION_ID"="PRD"."CODE_COMBINATION_ID")
3 - access("GLCC"."SEGMENT6"='03271')
filter(("GLCC"."SEGMENT2"='12145' OR "GLCC"."SEGMENT2"='12155'))
7 - filter("PRH"."TYPE_LOOKUP_CODE"='PURCHASE')
8 - access("PRH"."AUTHORIZATION_STATUS"='APPROVED')
10 - access("PRH"."REQUISITION_HEADER_ID"="PRL"."REQUISITION_HEADER_ID")
11 - access("PRD"."REQUISITION_LINE_ID"="PRL"."REQUISITION_LINE_ID")
********************************For the faster query estimated rows and actual rows are almost accurate in most cases. But for slower query estimates are horrendously wrong. Estimated rows are no where near to actual rows. Some cases estimated rows are just 1 but actual rows are 3 million. I checked the stats on those tables. Stats are looking good
Table name Stat Count Actual Count
PO_REQUISITION_LINES_ALL 3,158,548 3,166,998
PO_REQ_DISTRIBUTIONS_ALL 3,185,569 3,239,953
PO_REQUISITION_HEADERS_ALL 1,296,423 1,300,087
Then with this state do not know why the optimizer will predict so badly. Then i used hint /*+ dynamic_sampling(11) */ as you suggested, to my surprise i got the explain plan same as fast query and performance was also same. below is execution plan with hint.
***********************************
SQL_ID 7j0bhm4ung00c, child number 0
-------------------------------------
SELECT /*+ dynamic_sampling(11) */ Prh.Segment1 Pr_Num, --tst102
Prh.Description, Prh.Authorization_Status,
Prh.Creation_Date, Prl.Line_Num Pr_Line_Num,
Prl.Unit_Meas_Lookup_Code, Prl.Quantity, Prl.Unit_Price,
Prl.Item_Description, Prl.Line_Location_Id,
Prd.Distribution_Id, glcc.segment2 FROM
Apps.Po_Requisition_Headers_All Prh, Apps.Po_Requisition_Lines_All
Prl, Apps.Po_Req_Distributions_All Prd,
Apps.Gl_Code_Combinations Glcc WHERE Prh.Type_Lookup_Code = 'PURCHASE'
AND Prh.Authorization_Status = 'APPROVED' AND
Prh.Requisition_Header_Id = Prl.Requisition_Header_Id AND
Prd.Requisition_Line_Id = Prl.Requisition_Line_Id AND
Glcc.Code_Combination_Id = Prd.Code_Combination_Id AND Glcc.Segment2
IN ('12145', '12155') AND (Glcc.Segment6 ='03271' )
Plan hash value: 2128049585
---------------------------------------------------------------------------------------
| Id | Operation | Name | E-Rows |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | |
|* 1 | HASH JOIN | | 382 |
|* 2 | TABLE ACCESS BY INDEX ROWID BATCHED | GL_CODE_COMBINATIONS | 56 |
|* 3 | INDEX RANGE SCAN | GL_CODE_COMBINATIONS_N6 | 33 |
| 4 | NESTED LOOPS | | 401K|
| 5 | NESTED LOOPS | | 401K|
| 6 | NESTED LOOPS | | 397K|
|* 7 | TABLE ACCESS BY INDEX ROWID BATCHED| PO_REQUISITION_HEADERS_ALL | 162K|
|* 8 | INDEX RANGE SCAN | PO_REQUISITION_HEADERS_N3 | 1183K|
| 9 | TABLE ACCESS BY INDEX ROWID BATCHED| PO_REQUISITION_LINES_ALL | 2 |
|* 10 | INDEX RANGE SCAN | PO_REQUISITION_LINES_U2 | 2 |
|* 11 | INDEX RANGE SCAN | PO_REQ_DISTRIBUTIONS_N1 | 1 |
| 12 | TABLE ACCESS BY INDEX ROWID | PO_REQ_DISTRIBUTIONS_ALL | 1 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("GLCC"."CODE_COMBINATION_ID"="PRD"."CODE_COMBINATION_ID")
2 - filter(("GLCC"."SEGMENT2"='12145' OR "GLCC"."SEGMENT2"='12155'))
3 - access("GLCC"."SEGMENT6"='03271')
7 - filter("PRH"."TYPE_LOOKUP_CODE"='PURCHASE')
8 - access("PRH"."AUTHORIZATION_STATUS"='APPROVED')
10 - access("PRH"."REQUISITION_HEADER_ID"="PRL"."REQUISITION_HEADER_ID")
11 - access("PRD"."REQUISITION_LINE_ID"="PRL"."REQUISITION_LINE_ID")
Note
-----
- dynamic statistics used: dynamic sampling (level=0)
- Warning: basic plan statistics not available. These are only collected when:
* hint 'gather_plan_statistics' is used for the statement or
* parameter 'statistics_level' is set to 'ALL', at session or system level
*********************************** If you can explain me why would oracle predict so wrong in one case and predicts fine in another case and how dynamic sampling hint helps optimize and is there any criteria to decide level of dynamic sampling.
Just curious with hint i still see in execution plan "dynamic sampling (level=0)" but i passed it as 11.
Thanks you very much for your help and making our life easier with those tips and helps.
Cheers.
Ambuj