Adaptive Plans in Oracle Database 12c Release 1 (12.1)
See how the 12c optimizer uses adaptive plans to adjust executiuon plans on the fly.
oracle 12cconfigurationintermediate
by OracleDba
11 views
See how the 12c optimizer uses adaptive plans to adjust executiuon plans on the fly.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
CONN test/test@pdb1
DROP TABLE tab2 PURGE;
DROP SEQUENCE tab2_seq;
DROP TABLE tab1 PURGE;
DROP SEQUENCE tab1_seq;
CREATE TABLE tab1 (
id NUMBER,
code VARCHAR2(5),
data NUMBER(5),
CONSTRAINT tab1_pk PRIMARY KEY (id)
);
CREATE INDEX tab1_code ON tab1(code);
CREATE SEQUENCE tab1_seq;
INSERT INTO tab1 VALUES (tab1_seq.nextval, 'ONE', 1);
INSERT INTO tab1 VALUES (tab1_seq.nextval, 'TWO', 2);
INSERT INTO tab1 VALUES (tab1_seq.nextval, 'THREE', 3);
INSERT INTO tab1 VALUES (tab1_seq.nextval, 'FOUR', 4);
INSERT INTO tab1 VALUES (tab1_seq.nextval, 'FIVE', 5);
COMMIT;
CREATE TABLE tab2 (
id NUMBER,
tab1_id NUMBER,
data NUMBER(5),
CONSTRAINT tab2_pk PRIMARY KEY (id),
CONSTRAINT tab2_tab1_fk FOREIGN KEY (tab1_id) REFERENCES tab1(id)
);
CREATE SEQUENCE tab2_seq;
CREATE INDEX tab2_tab1_fki ON tab2(tab1_id);
INSERT /*+ APPEND */ INTO tab2
SELECT tab2_seq.nextval,
TRUNC(DBMS_RANDOM.value(1,5)),
level
FROM dual
CONNECT BY level <= 100;
COMMIT;
EXEC DBMS_STATS.gather_table_stats(USER, 'TAB1');
EXEC DBMS_STATS.gather_table_stats(USER, 'TAB2');
SELECT a.data AS tab1_data,
b.data AS tab2_data
FROM tab1 a
JOIN tab2 b ON b.tab1_id = a.id
WHERE a.code = 'ONE';
SET LINESIZE 200 PAGESIZE 100
SELECT * FROM TABLE(DBMS_XPLAN.display_cursor);
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------
SQL_ID 4r3harjun4dvz, child number 0
-------------------------------------
SELECT a.data AS tab1_data, b.data AS tab2_data FROM tab1 a
JOIN tab2 b ON b.tab1_id = a.id WHERE a.code = 'ONE'
Plan hash value: 2672205743
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100)| |
| 1 | NESTED LOOPS | | 25 | 425 | 3 (0)| 00:00:01 |
| 2 | NESTED LOOPS | | 25 | 425 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID BATCHED| TAB1 | 1 | 11 | 2 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | TAB1_CODE | 1 | | 1 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | TAB2_TAB1_FKI | 25 | | 0 (0)| |
| 6 | TABLE ACCESS BY INDEX ROWID | TAB2 | 25 | 150 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("A"."CODE"='ONE')
5 - access("B"."TAB1_ID"="A"."ID")
Note
-----
- this is an adaptive plan
SQL>
SELECT a.data AS tab1_data,
b.data AS tab2_data
FROM tab1 a
JOIN tab2 b ON b.tab1_id = a.id
WHERE a.code = 'ONE';
SET LINESIZE 200 PAGESIZE 100
SELECT * FROM TABLE(DBMS_XPLAN.display_cursor(format => 'adaptive'));
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------
SQL_ID 4r3harjun4dvz, child number 0
-------------------------------------
SELECT a.data AS tab1_data, b.data AS tab2_data FROM tab1 a
JOIN tab2 b ON b.tab1_id = a.id WHERE a.code = 'ONE'
Plan hash value: 2672205743
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100)| |
|- * 1 | HASH JOIN | | 25 | 425 | 3 (0)| 00:00:01 |
| 2 | NESTED LOOPS | | 25 | 425 | 3 (0)| 00:00:01 |
| 3 | NESTED LOOPS | | 25 | 425 | 3 (0)| 00:00:01 |
|- 4 | STATISTICS COLLECTOR | | | | | |
| 5 | TABLE ACCESS BY INDEX ROWID BATCHED| TAB1 | 1 | 11 | 2 (0)| 00:00:01 |
| * 6 | INDEX RANGE SCAN | TAB1_CODE | 1 | | 1 (0)| 00:00:01 |
| * 7 | INDEX RANGE SCAN | TAB2_TAB1_FKI | 25 | | 0 (0)| |
| 8 | TABLE ACCESS BY INDEX ROWID | TAB2 | 25 | 150 | 1 (0)| 00:00:01 |
|- 9 | TABLE ACCESS FULL | TAB2 | 25 | 150 | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("B"."TAB1_ID"="A"."ID")
6 - access("A"."CODE"='ONE')
7 - access("B"."TAB1_ID"="A"."ID")
Note
-----
- this is an adaptive plan (rows marked '-' are inactive)
SQL>
SELECT /*+ GATHER_PLAN_STATISTICS */
a.data AS tab1_data,
b.data AS tab2_data
FROM tab1 a
JOIN tab2 b ON b.tab1_id = a.id
WHERE a.code = 'ONE';
SET LINESIZE 200 PAGESIZE 100
SELECT * FROM TABLE(DBMS_XPLAN.display_cursor(format => 'adaptive allstats last'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------
SQL_ID 1km5kczcgr0fr, child number 0
-------------------------------------
SELECT /*+ GATHER_PLAN_STATISTICS */ a.data AS tab1_data,
b.data AS tab2_data FROM tab1 a JOIN tab2 b ON b.tab1_id =
a.id WHERE a.code = 'ONE'
Plan hash value: 2672205743
---------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 25 |00:00:00.01 | 8 |
|- * 1 | HASH JOIN | | 1 | 25 | 25 |00:00:00.01 | 8 |
| 2 | NESTED LOOPS | | 1 | 25 | 25 |00:00:00.01 | 8 |
| 3 | NESTED LOOPS | | 1 | 25 | 25 |00:00:00.01 | 5 |
|- 4 | STATISTICS COLLECTOR | | 1 | | 1 |00:00:00.01 | 2 |
| 5 | TABLE ACCESS BY INDEX ROWID BATCHED| TAB1 | 1 | 1 | 1 |00:00:00.01 | 2 |
| * 6 | INDEX RANGE SCAN | TAB1_CODE | 1 | 1 | 1 |00:00:00.01 | 1 |
| * 7 | INDEX RANGE SCAN | TAB2_TAB1_FKI | 1 | 25 | 25 |00:00:00.01 | 3 |
| 8 | TABLE ACCESS BY INDEX ROWID | TAB2 | 25 | 25 | 25 |00:00:00.01 | 3 |
|- 9 | TABLE ACCESS FULL | TAB2 | 0 | 25 | 0 |00:00:00.01 | 0 |
---------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("B"."TAB1_ID"="A"."ID")
6 - access("A"."CODE"='ONE')
7 - access("B"."TAB1_ID"="A"."ID")
Note
-----
- this is an adaptive plan (rows marked '-' are inactive)
SQL>
INSERT /*+ APPEND */ INTO tab1
SELECT tab1_seq.nextval,
'ONE',
level
FROM dual
CONNECT BY level <= 10000;
COMMIT;
INSERT /*+ APPEND */ INTO tab2
SELECT tab2_seq.nextval,
TRUNC(DBMS_RANDOM.value(11,10005)),
level
FROM dual
CONNECT BY level <= 10000;
COMMIT;
SELECT num_rows FROM user_tables WHERE table_name = 'TAB1';
NUM_ROWS
----------
5
SQL>
SELECT num_rows FROM user_tables WHERE table_name = 'TAB2';
NUM_ROWS
----------
100
SQL>
SELECT /*+ GATHER_PLAN_STATISTICS */
a.data AS tab1_data,
b.data AS tab2_data
FROM tab1 a
JOIN tab2 b ON b.tab1_id = a.id
WHERE a.code = 'ONE';
SET LINESIZE 200 PAGESIZE 100
SELECT * FROM TABLE(DBMS_XPLAN.display_cursor(format => 'allstats last adaptive'));
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------
SQL_ID 1km5kczcgr0fr, child number 0
-------------------------------------
SELECT /*+ GATHER_PLAN_STATISTICS */ a.data AS tab1_data,
b.data AS tab2_data FROM tab1 a JOIN tab2 b ON b.tab1_id =
a.id WHERE a.code = 'ONE'
Plan hash value: 2672205743
------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads |
------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 10025 |00:00:00.40 | 12623 | 30 |
|- * 1 | HASH JOIN | | 1 | 25 | 10025 |00:00:00.40 | 12623 | 30 |
| 2 | NESTED LOOPS | | 1 | 25 | 10025 |00:00:00.31 | 12623 | 30 |
| 3 | NESTED LOOPS | | 1 | 25 | 10025 |00:00:00.17 | 3042 | 30 |
|- 4 | STATISTICS COLLECTOR | | 1 | | 10001 |00:00:00.14 | 1431 | 30 |
| 5 | TABLE ACCESS BY INDEX ROWID BATCHED| TAB1 | 1 | 1 | 10001 |00:00:00.09 | 1431 | 30 |
| * 6 | INDEX RANGE SCAN | TAB1_CODE | 1 | 1 | 10001 |00:00:00.03 | 739 | 0 |
| * 7 | INDEX RANGE SCAN | TAB2_TAB1_FKI | 10001 | 25 | 10025 |00:00:00.07 | 1611 | 0 |
| 8 | TABLE ACCESS BY INDEX ROWID | TAB2 | 10025 | 25 | 10025 |00:00:00.07 | 9581 | 0 |
|- 9 | TABLE ACCESS FULL | TAB2 | 0 | 25 | 0 |00:00:00.01 | 0 | 0 |
------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("B"."TAB1_ID"="A"."ID")
6 - access("A"."CODE"='ONE')
7 - access("B"."TAB1_ID"="A"."ID")
Note
-----
- this is an adaptive plan (rows marked '-' are inactive)
SQL>
CONN sys@pdb1 AS SYSDBA
ALTER SYSTEM FLUSH SHARED_POOL;
CONN test/test@pdb1
SELECT /*+ GATHER_PLAN_STATISTICS */
a.data AS tab1_data,
b.data AS tab2_data
FROM tab1 a
JOIN tab2 b ON b.tab1_id = a.id
WHERE a.code = 'ONE';
SET LINESIZE 200 PAGESIZE 100
SELECT * FROM TABLE(DBMS_XPLAN.display_cursor(format => 'allstats last adaptive'));
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID 1km5kczcgr0fr, child number 0
-------------------------------------
SELECT /*+ GATHER_PLAN_STATISTICS */ a.data AS tab1_data,
b.data AS tab2_data FROM tab1 a JOIN tab2 b ON b.tab1_id =
a.id WHERE a.code = 'ONE'
Plan hash value: 1599395313
------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 10025 |00:00:00.04 | 760 | | | |
| * 1 | HASH JOIN | | 1 | 25 | 10025 |00:00:00.04 | 760 | 1899K| 1899K| 1944K (0)|
|- 2 | NESTED LOOPS | | 1 | 25 | 10001 |00:00:00.16 | 63 | | | |
|- 3 | NESTED LOOPS | | 1 | 25 | 10001 |00:00:00.12 | 63 | | | |
|- 4 | STATISTICS COLLECTOR | | 1 | | 10001 |00:00:00.09 | 63 | | | |
| 5 | TABLE ACCESS BY INDEX ROWID BATCHED| TAB1 | 1 | 1 | 10001 |00:00:00.06 | 63 | | | |
| * 6 | INDEX RANGE SCAN | TAB1_CODE | 1 | 1 | 10001 |00:00:00.02 | 37 | | | |
|- * 7 | INDEX RANGE SCAN | TAB2_TAB1_FKI | 0 | 25 | 0 |00:00:00.01 | 0 | | | |
|- 8 | TABLE ACCESS BY INDEX ROWID | TAB2 | 0 | 25 | 0 |00:00:00.01 | 0 | | | |
| 9 | TABLE ACCESS FULL | TAB2 | 1 | 25 | 10100 |00:00:00.03 | 697 | | | |
------------------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("B"."TAB1_ID"="A"."ID")
6 - access("A"."CODE"='ONE')
7 - access("B"."TAB1_ID"="A"."ID")
Note
-----
- this is an adaptive plan (rows marked '-' are inactive)
SQL>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
CONN test/test@pdb1
EXEC DBMS_STATS.gather_table_stats(USER, 'TAB1');
EXEC DBMS_STATS.gather_table_stats(USER, 'TAB2');
CONN sys@pdb1 AS SYSDBA
ALTER SYSTEM FLUSH SHARED_POOL;
CONN test/test@pdb1
SELECT /*+ GATHER_PLAN_STATISTICS
PARALLEL(16) */
a.data AS tab1_data,
b.data AS tab2_data
FROM tab1 a
JOIN tab2 b ON b.tab1_id = a.id
WHERE a.code = 'ONE';
SET LINESIZE 200 PAGESIZE 100
SELECT * FROM TABLE(DBMS_XPLAN.display_cursor(format => 'allstats last adaptive'));
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------------------
SQL_ID axw4khkastaz7, child number 0
-------------------------------------
SELECT /*+ GATHER_PLAN_STATISTICS PARALLEL(16) */
a.data AS tab1_data, b.data AS tab2_data FROM tab1 a
JOIN tab2 b ON b.tab1_id = a.id WHERE a.code = 'ONE'
Plan hash value: 1613349611
-----------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
-----------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 10029 |00:00:00.08 | 10 | | | |
| 1 | PX COORDINATOR | | 1 | | 10029 |00:00:00.08 | 10 | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10002 | 0 | 3178 | 0 |00:00:00.01 | 0 | | | |
|* 3 | HASH JOIN BUFFERED | | 0 | 3178 | 0 |00:00:00.01 | 0 | 2517K| 2517K| 2398K (0)|
| 4 | JOIN FILTER CREATE | :BF0000 | 0 | 2001 | 0 |00:00:00.01 | 0 | | | |
| 5 | PX RECEIVE | | 0 | 2001 | 0 |00:00:00.01 | 0 | | | |
| 6 |
PX SEND HYBRID HASH
| :TQ10000 | 0 | 2001 | 0 |00:00:00.01 | 0 | | | |
| 7 |
STATISTICS COLLECTOR
| | 0 | | 0 |00:00:00.01 | 0 | | | |
| 8 | PX BLOCK ITERATOR | | 0 | 2001 | 0 |00:00:00.01 | 0 | | | |
|* 9 | TABLE ACCESS FULL | TAB1 | 0 | 2001 | 0 |00:00:00.01 | 0 | | | |
| 10 | PX RECEIVE | | 0 | 10100 | 0 |00:00:00.01 | 0 | | | |
| 11 |
PX SEND HYBRID HASH
| :TQ10001 | 0 | 10100 | 0 |00:00:00.01 | 0 | | | |
| 12 | JOIN FILTER USE | :BF0000 | 0 | 10100 | 0 |00:00:00.01 | 0 | | | |
| 13 | PX BLOCK ITERATOR | | 0 | 10100 | 0 |00:00:00.01 | 0 | | | |
|* 14 | TABLE ACCESS FULL | TAB2 | 0 | 10100 | 0 |00:00:00.01 | 0 | | | |
-----------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("B"."TAB1_ID"="A"."ID")
9 - access(:Z>=:Z AND :Z<=:Z)
filter("A"."CODE"='ONE')
14 - access(:Z>=:Z AND :Z<=:Z)
filter(SYS_OP_BLOOM_FILTER(:BF0000,"B"."TAB1_ID"))
Note
-----
- Degree of Parallelism is 16 because of hint
SQL>123
optimizer_adaptive_features boolean TRUE
optimizer_adaptive_reporting_only boolean FALSE
optimizer_features_enable string 12.1.0.1Please to add comments
No comments yet. Be the first to comment!