The tkprof output says that Oracle is doing a hash join instead of a merge join, it’s swapped the join order, and the estimate for table rows is 54,902 rather than 128K.

Looking at the run-time plan we can now see that the “single” partition range has pstart/pstop of KEY/KEY. I should have noticed earlier that your input date is using a two-digit year, which means Oracle doesn’t know how to interpret it until run time – so instead of using partition-level stats throughout it’s (probably) used some partition-level and some global level stats, resulting in the contradictory estimates you see. Always use a proper date, or a complete date string with full explicit conversion.

]]>Hi Jonathan,

I apologize for posting a question here, but I wanted to get your opinion about this behavior. Thank you for providing your inputs.

I have requested DBA to check with oracle support.

To further understand this behavior, I generated trace for this SQL and found that oracle is using same plan and cardinality at runtime.

Rows (1st) Rows (avg) Rows (max) Row Source Operation ---------- ---------- ---------- --------------------------------------------------- 13 13 13 HASH UNIQUE (cr=559 pr=0 pw=0 time=22742 us cost=123 size=4212 card=117) 21 21 21 HASH JOIN (cr=559 pr=0 pw=0 time=8073 us cost=122 size=4212 card=117) 106 106 106 INLIST ITERATOR (cr=206 pr=0 pw=0 time=2128 us) 106 106 106 TABLE ACCESS BY INDEX ROWID T_ACCOUNT (cr=206 pr=0 pw=0 time=690 us cost=38 size=1696 card=106) 106 106 106 INDEX UNIQUE SCAN PK_T_ACCOUNT (cr=149 pr=0 pw=0 time=308 us cost=29 size=0 card=106)(object id 597788) 21 21 21 PARTITION RANGE SINGLE PARTITION: KEY KEY (cr=353 pr=0 pw=0 time=376 us cost=83 size=1098040 card=54902) 21 21 21 INLIST ITERATOR (cr=353 pr=0 pw=0 time=356 us) 21 21 21 TABLE ACCESS BY LOCAL INDEX ROWID T_ACCT_SUM PARTITION: KEY KEY (cr=353 pr=0 pw=0 time=1194 us cost=83 size=1098040 card=54902) 214 214 214 INDEX RANGE SCAN PK_T_ACCT_SUM PARTITION: KEY KEY (cr=186 pr=0 pw=0 time=491 us cost=32 size=0 card=5)(object id 603269)

Also, I tried changing In-LIST condition “T_ACCOUNT.AC_SK IN (” to “T_ACCT_SUM.AC_SK IN (” (as this column is used in join condition and should not change the logic), and that SQL predicted correct cardinality changing original hash join to nested loops.

---------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ---------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 54 | 1944 | 104 (1)| | 1 | HASH UNIQUE | | 54 | 1944 | 104 (1)| | 2 | NESTED LOOPS | | | | | | 3 | NESTED LOOPS | | 54 | 1944 | 103 (0)| | 4 | PARTITION RANGE SINGLE | | 54 | 1080 | 87 (0)| | 5 | INLIST ITERATOR | | | | | |* 6 | TABLE ACCESS BY LOCAL INDEX ROWID| T_ACCT_SUM | 54 | 1080 | 87 (0)| |* 7 | INDEX RANGE SCAN | PK_T_ACCT_SUM | 6 | | 32 (0)| |* 8 | INDEX UNIQUE SCAN | PK_T_ACCOUNT | 1 | | 1 (0)| | 9 | TABLE ACCESS BY INDEX ROWID | T_ACCOUNT | 1 | 16 | 1 (0)| ----------------------------------------------------------------------------------------------------

Thanks,

-Amit.

Amit,

This isn’t a forum – your question is the type of thing that can be addressed by members of the OTN database forum or the Oracle-L list.

Having said that – explain plan is probably showing you the plan that would be used at run-time; and it’s saying “partition range single”, so the stats used should be the partition-level stats. This being the case it ought to be relatively simple for the optimizer to be consistent between the index and table (in this version of Oracle). My guess is that the optimizer has managed to take a code path that doesn’t allow for the inlist iterator when considering index selectivity, and then used a different strategy for the table selectivity. Whatever it has done it’s clearly a defect when when the number of rows predicted for the table exceeds the number of rowids predicted by the index access, so I’d raise it with Oracle Support.

]]>I have following query and I generated execution plan for it. I am not able to understand the cardinality.

Query : SELECT DISTINCT T_ACCOUNT.AC_SK, T_ACCT_SUM.ACCT_BAL, T_ACCOUNT.AC_ID FROM T_ACCOUNT, T_ACCT_SUM WHERE T_ACCOUNT.AC_SK IN (167056,276364,292510,410216,550806,584324,584325,585607,594305,594306,375386,375387,597632,597633,5 97634,597636,597637,597638,597639,597640,597641,597642,597643,597644,597645,597646,597647,597648,597 649,597650,597651,597652,597653,597654,597655,597665,597656,597657,597658,597659,597660,597661,59766 2,597663,597664,597625,597626,597627,608683,709753,739855,769598,769599,769600,789267,831812,831816, 831815,831814,831813,831817,886799,891301,891302,896746,905441,928452,952683,971664,971665,971666,97 1667,971668,971669,971670,597628,597629,986885,987360,987859,992765,1069330,1070973,1075750,1201860, 1201862,1201861,1283345,1283346,1312703,1312704,1312702,1312578,1312579,1415629,1446799,1446798,1520 530,1834159,1859876,1894444,1932920,1964377,2033976,2077465,2185914) AND T_ACCT_SUM.ACCT_BAL <= 1000.00 AND T_ACCOUNT.AC_SK = T_ACCT_SUM.AC_SK AND T_ACCT_SUM.BAL_DATE = '31-OCT-13'; Execution plan : -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 132 | 4752 | 124 (2)| | 1 | HASH UNIQUE | | 132 | 4752 | 124 (2)| | 2 | MERGE JOIN | | 132 | 4752 | 123 (1)| | 3 | PARTITION RANGE SINGLE | | 128K| 2501K| 85 (0)| | 4 | INLIST ITERATOR | | | | | |* 5 | TABLE ACCESS BY LOCAL INDEX ROWID| T_ACCT_SUM | 128K| 2501K| 85 (0)| |* 6 | INDEX RANGE SCAN | PK_T_ACCT_SUM | 5 | | 32 (0)| |* 7 | SORT JOIN | | 106 | 1696 | 39 (3)| | 8 | INLIST ITERATOR | | | | | | 9 | TABLE ACCESS BY INDEX ROWID | T_ACCOUNT | 106 | 1696 | 38 (0)| |* 10 | INDEX UNIQUE SCAN | PK_T_ACCOUNT | 106 | | 29 (0)| -------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 5 - filter("T_ACCT_SUM"."ACCT_BAL"<=1000.00) 6 - access(("T_ACCT_SUM"."AC_SK"=167056 OR "T_ACCT_SUM"."AC_SK"=276364 OR "T_ACCT_SUM"."AC_SK"=292510 OR "T_ACCT_SUM"."AC_SK"=375386 OR "T_ACCT_SUM"."AC_SK"=375387 OR "T_ACCT_SUM"."AC_SK"=410216 OR "T_ACCT_SUM"."AC_SK"=550806 OR "T_ACCT_SUM"."AC_SK"=584324 OR "T_ACCT_SUM"."AC_SK"=584325 OR "T_ACCT_SUM"."AC_SK"=585607 OR "T_ACCT_SUM"."AC_SK"=594305 OR "T_ACCT_SUM"."AC_SK"=594306 OR "T_ACCT_SUM"."AC_SK"=597625 OR "T_ACCT_SUM"."AC_SK"=597626 OR "T_ACCT_SUM"."AC_SK"=597627 OR "T_ACCT_SUM"."AC_SK"=597628 OR "T_ACCT_SUM"."AC_SK"=597629 OR "T_ACCT_SUM"."AC_SK"=597632 OR "T_ACCT_SUM"."AC_SK"=597633 OR "T_ACCT_SUM"."AC_SK"=597634 OR "T_ACCT_SUM"."AC_SK"=597636 OR "T_ACCT_SUM"."AC_SK"=597637 OR "T_ACCT_SUM"."AC_SK"=597638 OR "T_ACCT_SUM"."AC_SK"=597639 OR "T_ACCT_SUM"."AC_SK"=597640 OR "T_ACCT_SUM"."AC_SK"=597641 OR "T_ACCT_SUM"."AC_SK"=597642 OR "T_ACCT_SUM"."AC_SK"=597643 OR "T_ACCT_SUM"."AC_SK"=597644 OR "T_ACCT_SUM"."AC_SK"=597645 OR "T_ACCT_SUM"."AC_SK"=597646 OR "T_ACCT_SUM"."AC_SK"=597647 OR "T_ACCT_SUM"."AC_SK"=597648 OR "T_ACCT_SUM"."AC_SK"=597649 OR "T_ACCT_SUM"."AC_SK"=597650 OR "T_ACCT_SUM"."AC_SK"=597651 OR "T_ACCT_SUM"."AC_SK"=597652 OR "T_ACCT_SUM"."AC_SK"=597653 OR "T_ACCT_SUM"."AC_SK"=597654 OR "T_ACCT_SUM"."AC_SK"=597655 OR "T_ACCT_SUM"."AC_SK"=597656 OR "T_ACCT_SUM"."AC_SK"=597657 OR "T_ACCT_SUM"."AC_SK"=597658 OR "T_ACCT_SUM"."AC_SK"=597659 OR "T_ACCT_SUM"."AC_SK"=597660 OR "T_ACCT_SUM"."AC_SK"=597661 OR "T_ACCT_SUM"."AC_SK"=597662 OR "T_ACCT_SUM"."AC_SK"=597663 OR "T_ACCT_SUM"."AC_SK"=597664 OR "T_ACCT_SUM"."AC_SK"=597665 OR "T_ACCT_SUM"."AC_SK"=608683 OR "T_ACCT_SUM"."AC_SK"=709753 OR "T_ACCT_SUM"."AC_SK"=739855 OR "T_ACCT_SUM"."AC_SK"=769598 OR "T_ACCT_SUM"."AC_SK"=769599 OR "T_ACCT_SUM"."AC_SK"=769600 OR "T_ACCT_SUM"."AC_SK"=789267 OR "T_ACCT_SUM"."AC_SK"=831812 OR "T_ACCT_SUM"."AC_SK"=831813 OR "T_ACCT_SUM"."AC_SK"=831814 OR "T_ACCT_SUM"."AC_SK"=831815 OR "T_ACCT_SUM"."AC_SK"=831816 OR "T_ACCT_SUM"."AC_SK"=831817 OR "T_ACCT_SUM"."AC_SK"=886799 OR "T_ACCT_SUM"."AC_SK"=891301 OR "T_ACCT_SUM"."AC_SK"=891302 OR "T_ACCT_SUM"."AC_SK"=896746 OR "T_ACCT_SUM"."AC_SK"=905441 OR "T_ACCT_SUM"."AC_SK"=928452 OR "T_ACCT_SUM"."AC_SK"=952683 OR "T_ACCT_SUM"."AC_SK"=971664 OR "T_ACCT_SUM"."AC_SK"=971665 OR "T_ACCT_SUM"."AC_SK"=971666 OR "T_ACCT_SUM"."AC_SK"=971667 OR "T_ACCT_SUM"."AC_SK"=971668 OR "T_ACCT_SUM"."AC_SK"=971669 OR "T_ACCT_SUM"."AC_SK"=971670 OR "T_ACCT_SUM"."AC_SK"=986885 OR "T_ACCT_SUM"."AC_SK"=987360 OR "T_ACCT_SUM"."AC_SK"=987859 OR "T_ACCT_SUM"."AC_SK"=992765 OR "T_ACCT_SUM"."AC_SK"=1069330 OR "T_ACCT_SUM"."AC_SK"=1070973 OR "T_ACCT_SUM"."AC_SK"=1075750 OR "T_ACCT_SUM"."AC_SK"=1201860 OR "T_ACCT_SUM"."AC_SK"=1201861 OR "T_ACCT_SUM"."AC_SK"=1201862 OR "T_ACCT_SUM"."AC_SK"=1283345 OR "T_ACCT_SUM"."AC_SK"=1283346 OR "T_ACCT_SUM"."AC_SK"=1312578 OR "T_ACCT_SUM"."AC_SK"=1312579 OR "T_ACCT_SUM"."AC_SK"=1312702 OR "T_ACCT_SUM"."AC_SK"=1312703 OR "T_ACCT_SUM"."AC_SK"=1312704 OR "T_ACCT_SUM"."AC_SK"=1415629 OR "T_ACCT_SUM"."AC_SK"=1446798 OR "T_ACCT_SUM"."AC_SK"=1446799 OR "T_ACCT_SUM"."AC_SK"=1520530 OR "T_ACCT_SUM"."AC_SK"=1834159 OR "T_ACCT_SUM"."AC_SK"=1859876 OR "T_ACCT_SUM"."AC_SK"=1894444 OR "T_ACCT_SUM"."AC_SK"=1932920 OR "T_ACCT_SUM"."AC_SK"=1964377 OR "T_ACCT_SUM"."AC_SK"=2033976 OR "T_ACCT_SUM"."AC_SK"=2077465 OR "T_ACCT_SUM"."AC_SK"=2185914) AND "T_ACCT_SUM"."VALN_AS_OF_DATE"='31-OCT-13') 7 - access("T_ACCOUNT"."AC_SK"="T_ACCT_SUM"."AC_SK") filter("T_ACCOUNT"."AC_SK"="T_ACCT_SUM"."AC_SK") 10 - access("T_ACCOUNT"."AC_SK"=167056 OR "T_ACCOUNT"."AC_SK"=276364 OR "T_ACCOUNT"."AC_SK"=292510 OR "T_ACCOUNT"."AC_SK"=375386 OR "T_ACCOUNT"."AC_SK"=375387 OR "T_ACCOUNT"."AC_SK"=410216 OR "T_ACCOUNT"."AC_SK"=550806 OR "T_ACCOUNT"."AC_SK"=584324 OR "T_ACCOUNT"."AC_SK"=584325 OR "T_ACCOUNT"."AC_SK"=585607 OR "T_ACCOUNT"."AC_SK"=594305 OR "T_ACCOUNT"."AC_SK"=594306 OR "T_ACCOUNT"."AC_SK"=597625 OR "T_ACCOUNT"."AC_SK"=597626 OR "T_ACCOUNT"."AC_SK"=597627 OR "T_ACCOUNT"."AC_SK"=597628 OR "T_ACCOUNT"."AC_SK"=597629 OR "T_ACCOUNT"."AC_SK"=597632 OR "T_ACCOUNT"."AC_SK"=597633 OR "T_ACCOUNT"."AC_SK"=597634 OR "T_ACCOUNT"."AC_SK"=597636 OR "T_ACCOUNT"."AC_SK"=597637 OR "T_ACCOUNT"."AC_SK"=597638 OR "T_ACCOUNT"."AC_SK"=597639 OR "T_ACCOUNT"."AC_SK"=597640 OR "T_ACCOUNT"."AC_SK"=597641 OR "T_ACCOUNT"."AC_SK"=597642 OR "T_ACCOUNT"."AC_SK"=597643 OR "T_ACCOUNT"."AC_SK"=597644 OR "T_ACCOUNT"."AC_SK"=597645 OR "T_ACCOUNT"."AC_SK"=597646 OR "T_ACCOUNT"."AC_SK"=597647 OR "T_ACCOUNT"."AC_SK"=597648 OR "T_ACCOUNT"."AC_SK"=597649 OR "T_ACCOUNT"."AC_SK"=597650 OR "T_ACCOUNT"."AC_SK"=597651 OR "T_ACCOUNT"."AC_SK"=597652 OR "T_ACCOUNT"."AC_SK"=597653 OR "T_ACCOUNT"."AC_SK"=597654 OR "T_ACCOUNT"."AC_SK"=597655 OR "T_ACCOUNT"."AC_SK"=597656 OR "T_ACCOUNT"."AC_SK"=597657 OR "T_ACCOUNT"."AC_SK"=597658 OR "T_ACCOUNT"."AC_SK"=597659 OR "T_ACCOUNT"."AC_SK"=597660 OR "T_ACCOUNT"."AC_SK"=597661 OR "T_ACCOUNT"."AC_SK"=597662 OR "T_ACCOUNT"."AC_SK"=597663 OR "T_ACCOUNT"."AC_SK"=597664 OR "T_ACCOUNT"."AC_SK"=597665 OR "T_ACCOUNT"."AC_SK"=608683 OR "T_ACCOUNT"."AC_SK"=709753 OR "T_ACCOUNT"."AC_SK"=739855 OR "T_ACCOUNT"."AC_SK"=769598 OR "T_ACCOUNT"."AC_SK"=769599 OR "T_ACCOUNT"."AC_SK"=769600 OR "T_ACCOUNT"."AC_SK"=789267 OR "T_ACCOUNT"."AC_SK"=831812 OR "T_ACCOUNT"."AC_SK"=831813 OR "T_ACCOUNT"."AC_SK"=831814 OR "T_ACCOUNT"."AC_SK"=831815 OR "T_ACCOUNT"."AC_SK"=831816 OR "T_ACCOUNT"."AC_SK"=831817 OR "T_ACCOUNT"."AC_SK"=886799 OR "T_ACCOUNT"."AC_SK"=891301 OR "T_ACCOUNT"."AC_SK"=891302 OR "T_ACCOUNT"."AC_SK"=896746 OR "T_ACCOUNT"."AC_SK"=905441 OR "T_ACCOUNT"."AC_SK"=928452 OR "T_ACCOUNT"."AC_SK"=952683 OR "T_ACCOUNT"."AC_SK"=971664 OR "T_ACCOUNT"."AC_SK"=971665 OR "T_ACCOUNT"."AC_SK"=971666 OR "T_ACCOUNT"."AC_SK"=971667 OR "T_ACCOUNT"."AC_SK"=971668 OR "T_ACCOUNT"."AC_SK"=971669 OR "T_ACCOUNT"."AC_SK"=971670 OR "T_ACCOUNT"."AC_SK"=986885 OR "T_ACCOUNT"."AC_SK"=987360 OR "T_ACCOUNT"."AC_SK"=987859 OR "T_ACCOUNT"."AC_SK"=992765 OR "T_ACCOUNT"."AC_SK"=1069330 OR "T_ACCOUNT"."AC_SK"=1070973 OR "T_ACCOUNT"."AC_SK"=1075750 OR "T_ACCOUNT"."AC_SK"=1201860 OR "T_ACCOUNT"."AC_SK"=1201861 OR "T_ACCOUNT"."AC_SK"=1201862 OR "T_ACCOUNT"."AC_SK"=1283345 OR "T_ACCOUNT"."AC_SK"=1283346 OR "T_ACCOUNT"."AC_SK"=1312578 OR "T_ACCOUNT"."AC_SK"=1312579 OR "T_ACCOUNT"."AC_SK"=1312702 OR "T_ACCOUNT"."AC_SK"=1312703 OR "T_ACCOUNT"."AC_SK"=1312704 OR "T_ACCOUNT"."AC_SK"=1415629 OR "T_ACCOUNT"."AC_SK"=1446798 OR "T_ACCOUNT"."AC_SK"=1446799 OR "T_ACCOUNT"."AC_SK"=1520530 OR "T_ACCOUNT"."AC_SK"=1834159 OR "T_ACCOUNT"."AC_SK"=1859876 OR "T_ACCOUNT"."AC_SK"=1894444 OR "T_ACCOUNT"."AC_SK"=1932920 OR "T_ACCOUNT"."AC_SK"=1964377 OR "T_ACCOUNT"."AC_SK"=2033976 OR "T_ACCOUNT"."AC_SK"=2077465 OR "T_ACCOUNT"."AC_SK"=2185914)

Table T_ACCT_SUM is range partitioned on BAL_DATE column. ACCT_BAL column has height balanced

histogram.

Database is 11.2.0.3 version 4 node RAC system.

Execution plan is collected using "SET AUTOTRACE ON" command.

On line 6, cardinality calculated is "5" using index range scan. But on line 5, cardinality has

increased to 128K for same table. My assumption was that, cardinality returned by index should be

greater than or same as the cardinality for its corresponding table. Here, the increase is huge.

Can you please help me understand what I am missing?

Thanks!

]]>Regards

Vivek

Gary,

Yes, and it looks like a trend, but it’s still very limited.

Isn’t that what adaptive cursor sharing in 11g is about – alebit limited to circumstances where there may be skew relating to bind variables ? ]]>

I just wanted to point out that in cases where you have statements that take simply too long to complete for a full analysis e.g. using DBMS_XPLAN.DISPLAY_CURSOR, it still can be useful to run them with row source statistics enabled, because (at least in recent releases, e.g. 10.2.0.4) the row source statistics get refreshed even when canceling the execution after a while.

So using e.g. DBMS_XPLAN.DISPLAY_CURSOR on that incomplete execution reveals the part of the execution plan where the time was spent so far and allows to pinpoint any discrepancies in estimates and actual row source statistics without having to wait for the completion of the statement.

I guess this should have worked with Michelle’s particular example, too.

Regards,

Randolf

Okay, we can compare E-rows and A-rows to find out where the problem lies. Wouldn’t it be nice if Oracle could do this itself? After completing a query it can (theoretically) compare predicted and actual numbers and “fine-tune” statistics (probably new types of statistics) to reflect the difference. And the query will run faster next time, automagically.

Too fantastic? What do you think about it? ]]>