Here is a zip of two examples I built as I’m learning about the new adaptive plans features of Oracle 12c: zip
The first example has the optimizer underestimate the number of rows and the adaptive plans feature switches the plan on the fly from nested loops to hash join.
In the second example the optimizer overestimates the number of rows and the adaptive plans feature switches the plan from merge join to nested loops.
I ran the same scripts on 12c and 11.2.0.3 for comparison.
Example 1 11g:
Plan hash value: 2697562628 ------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 18 | | 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 18 | | 2 | NESTED LOOPS | | 1 | | 8 |00:00:00.01 | 18 | | 3 | NESTED LOOPS | | 1 | 1 | 8 |00:00:00.01 | 17 | |* 4 | TABLE ACCESS FULL | T1 | 1 | 1 | 8 |00:00:00.01 | 14 | |* 5 | INDEX RANGE SCAN | T2I | 8 | 1 | 8 |00:00:00.01 | 3 | | 6 | TABLE ACCESS BY INDEX ROWID| T2 | 8 | 1 | 8 |00:00:00.01 | 1 | ------------------------------------------------------------------------------------------------
Example 1 12c:
----------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | O/1/M | ----------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 6 | | | | | 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 6 | | | | |* 2 | HASH JOIN | | 1 | 1 | 8 |00:00:00.01 | 6 | 2168K| 2168K| 1/0/0| |* 3 | TABLE ACCESS FULL| T1 | 1 | 1 | 8 |00:00:00.01 | 3 | | | | | 4 | TABLE ACCESS FULL| T2 | 1 | 1 | 16 |00:00:00.01 | 3 | | | | -----------------------------------------------------------------------------------------------------------------
Example 2 11g
--------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | O/1/M | --------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 16 | | | | | 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 16 | | | | | 2 | MERGE JOIN | | 1 | 4 | 1 |00:00:00.01 | 16 | | | | | 3 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 16 | 2 |00:00:00.01 | 2 | | | | | 4 | INDEX FULL SCAN | T2I | 1 | 16 | 2 |00:00:00.01 | 1 | | | | |* 5 | SORT JOIN | | 2 | 4 | 1 |00:00:00.01 | 14 | 73728 | 73728 | | |* 6 | TABLE ACCESS FULL | T1 | 1 | 4 | 1 |00:00:00.01 | 14 | | | | ---------------------------------------------------------------------------------------------------------------------------
Example 2 12c
------------------------------------------------------------------------------------------------ | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 5 | | 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 5 | | 2 | NESTED LOOPS | | 1 | | 1 |00:00:00.01 | 5 | | 3 | NESTED LOOPS | | 1 | 4 | 1 |00:00:00.01 | 4 | |* 4 | TABLE ACCESS FULL | T1 | 1 | 4 | 1 |00:00:00.01 | 3 | |* 5 | INDEX RANGE SCAN | T2I | 1 | | 1 |00:00:00.01 | 1 | | 6 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 1 | 1 |00:00:00.01 | 1 | ------------------------------------------------------------------------------------------------
The output of the plans for the 12c examples end with this line:
Note ----- - this is an adaptive plan
So, that tells me it is the adaptive plan feature that is changing the plan despite the wrong estimate of the number of rows.
– Bobby
