- Optimizer-Mode
- Direct-Path
- Anpassungen von Cardinality-Schätzungen
- Bug-Handhabung
- Cursor-Sharing
- Parallelisierung
- Caching
- ...
Eine Liste verfügbarer Hints liefert V$SQL_HINT.
cost = blevelVöllig unproblematisch sind in dieser Rechnung die Faktoren blevel, leaf_blocks und clustering_factor, die man z.B. in der View user_indexes findet. Die beiden anderen Elemente effective index selectivity und effective table selectivity werden im CBO-Buch ebenfalls erläutert, aber ich hatte mir bisher nie die Mühe gemacht, zu prüfen, ob ich diese Erklärungen tatsächlich verstanden hatte. Das soll hiermit geändert werden.
+ ceiling(leaf_blocks * effective index selectivity)
+ ceiling(clustering_factor * effective table selectivity)
-- Anlage einer Test-Tabelle mit einem zusammengesetzten Index drop table test_ind_selectivity; create table test_ind_selectivity tablespace test_ts as select rownum id , mod(rownum, 10) col1 -- 10 unterschiedliche Werte -> Selektivität: 0,1 , mod(rownum, 100) col2 -- 100 unterschiedliche Werte -> Selektivität: 0,01 , mod(rownum, 1000) col3 -- 1000 unterschiedliche Werte -> Selektivität: 0,001 , lpad('*', 100, '*') pad from dual connect by level <= 1000000; exec dbms_stats.gather_table_stats(user, 'TEST_IND_SELECTIVITY', method_opt=>'FOR ALL COLUMNS SIZE 1') create index test_ind_selectivity_ix1 on test_ind_selectivity(col1, col2, col3);
select index_name , blevel , leaf_blocks , clustering_factor from user_indexes where table_name = upper('test_ind_selectivity'); INDEX_NAME BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR ------------------------------ ---------- ----------- ----------------- TEST_IND_SELECTIVITY_IX1 2 2894 1000000
ALTER SESSION SET EVENTS '10053 trace name context forever, level 1'; select /*+ index(test_ind_selectivity) test1 */ count(id) from test_ind_selectivity where col1 = 1; select /*+ index(test_ind_selectivity) test2 */ count(id) from test_ind_selectivity where col1 = 1 and col2 = 1; select /*+ index(test_ind_selectivity) test3 */ count(id) from test_ind_selectivity where col1 = 1 and col2 = 1 and col3 = 1; select /*+ index(test_ind_selectivity) test4 */ count(id) from test_ind_selectivity where col1 = 1 and col3 = 1; ALTER SESSION SET EVENTS '10053 trace name context OFF';
*************************************** BASE STATISTICAL INFORMATION *********************** Table Stats:: Table: TEST_IND_SELECTIVITY Alias: TEST_IND_SELECTIVITY #Rows: 1000000 #Blks: 16907 AvgRowLen: 116.00 Index Stats:: Index: TEST_IND_SELECTIVITY_IX1 Col#: 2 3 4 LVLS: 2 #LB: 2894 #DK: 1000 LB/K: 2.00 DB/K: 1000.00 CLUF: 1000000.00 User hint to use this index Access path analysis for TEST_IND_SELECTIVITY *************************************** SINGLE TABLE ACCESS PATH Single Table Cardinality Estimation for TEST_IND_SELECTIVITY[TEST_IND_SELECTIVITY] Table: TEST_IND_SELECTIVITY Alias: TEST_IND_SELECTIVITY Card: Original: 1000000.000000 Rounded: 100000 Computed: 100000.00 Non Adjusted: 100000.00 Access Path: index (RangeScan) Index: TEST_IND_SELECTIVITY_IX1 resc_io: 100292.00 resc_cpu: 751223460 ix_sel: 0.100000 ix_sel_with_filters: 0.100000 Cost: 100292.15 Resp: 100292.15 Degree: 1 Best:: AccessPath: IndexRange Index: TEST_IND_SELECTIVITY_IX1 Cost: 100292.15 Degree: 1 Resp: 100292.15 Card: 100000.00 Bytes: 0 ***************************************
*************************************** BASE STATISTICAL INFORMATION *********************** Table Stats:: Table: TEST_IND_SELECTIVITY Alias: TEST_IND_SELECTIVITY #Rows: 1000000 #Blks: 16907 AvgRowLen: 116.00 Index Stats:: Index: TEST_IND_SELECTIVITY_IX1 Col#: 2 3 4 LVLS: 2 #LB: 2894 #DK: 1000 LB/K: 2.00 DB/K: 1000.00 CLUF: 1000000.00 User hint to use this index Access path analysis for TEST_IND_SELECTIVITY *************************************** SINGLE TABLE ACCESS PATH Single Table Cardinality Estimation for TEST_IND_SELECTIVITY[TEST_IND_SELECTIVITY] ColGroup (#1, Index) TEST_IND_SELECTIVITY_IX1 Col#: 2 3 4 CorStregth: -1.00 ColGroup Usage:: PredCnt: 2 Matches Full: Partial: Table: TEST_IND_SELECTIVITY Alias: TEST_IND_SELECTIVITY Card: Original: 1000000.000000 Rounded: 1000 Computed: 1000.00 Non Adjusted: 1000.00 ColGroup Usage:: PredCnt: 2 Matches Full: Partial: ColGroup Usage:: PredCnt: 2 Matches Full: Partial: Access Path: index (RangeScan) Index: TEST_IND_SELECTIVITY_IX1 resc_io: 1005.00 resc_cpu: 7547047 ix_sel: 0.001000 ix_sel_with_filters: 0.001000 Cost: 1005.00 Resp: 1005.00 Degree: 1 Best:: AccessPath: IndexRange Index: TEST_IND_SELECTIVITY_IX1 Cost: 1005.00 Degree: 1 Resp: 1005.00 Card: 1000.00 Bytes: 0 ***************************************
*************************************** BASE STATISTICAL INFORMATION *********************** Table Stats:: Table: TEST_IND_SELECTIVITY Alias: TEST_IND_SELECTIVITY #Rows: 1000000 #Blks: 16907 AvgRowLen: 116.00 Index Stats:: Index: TEST_IND_SELECTIVITY_IX1 Col#: 2 3 4 LVLS: 2 #LB: 2894 #DK: 1000 LB/K: 2.00 DB/K: 1000.00 CLUF: 1000000.00 User hint to use this index Access path analysis for TEST_IND_SELECTIVITY *************************************** SINGLE TABLE ACCESS PATH Single Table Cardinality Estimation for TEST_IND_SELECTIVITY[TEST_IND_SELECTIVITY] ColGroup (#1, Index) TEST_IND_SELECTIVITY_IX1 Col#: 2 3 4 CorStregth: 1000.00 ColGroup Usage:: PredCnt: 3 Matches Full: #1 Partial: Sel: 0.0010 Table: TEST_IND_SELECTIVITY Alias: TEST_IND_SELECTIVITY Card: Original: 1000000.000000 Rounded: 1000 Computed: 1000.00 Non Adjusted: 1000.00 ColGroup Usage:: PredCnt: 3 Matches Full: #1 Partial: Sel: 0.0010 ColGroup Usage:: PredCnt: 3 Matches Full: #1 Partial: Sel: 0.0010 Access Path: index (AllEqRange) Index: TEST_IND_SELECTIVITY_IX1 resc_io: 1005.00 resc_cpu: 7567047 ix_sel: 0.001000 ix_sel_with_filters: 0.001000 Cost: 1005.00 Resp: 1005.00 Degree: 1 Best:: AccessPath: IndexRange Index: TEST_IND_SELECTIVITY_IX1 Cost: 1005.00 Degree: 1 Resp: 1005.00 Card: 1000.00 Bytes: 0 ***************************************
*************************************** BASE STATISTICAL INFORMATION *********************** Table Stats:: Table: TEST_IND_SELECTIVITY Alias: TEST_IND_SELECTIVITY #Rows: 1000000 #Blks: 16907 AvgRowLen: 116.00 Index Stats:: Index: TEST_IND_SELECTIVITY_IX1 Col#: 2 3 4 LVLS: 2 #LB: 2894 #DK: 1000 LB/K: 2.00 DB/K: 1000.00 CLUF: 1000000.00 User hint to use this index Access path analysis for TEST_IND_SELECTIVITY *************************************** SINGLE TABLE ACCESS PATH Single Table Cardinality Estimation for TEST_IND_SELECTIVITY[TEST_IND_SELECTIVITY] ColGroup (#1, Index) TEST_IND_SELECTIVITY_IX1 Col#: 2 3 4 CorStregth: -1.00 ColGroup Usage:: PredCnt: 2 Matches Full: Partial: #1 (2 4 ) Sel: 0.0010 Table: TEST_IND_SELECTIVITY Alias: TEST_IND_SELECTIVITY Card: Original: 1000000.000000 Rounded: 1000 Computed: 1000.00 Non Adjusted: 1000.00 kkofmx: index filter:"TEST_IND_SELECTIVITY"."COL3"=1 ColGroup Usage:: PredCnt: 2 Matches Full: Partial: #1 (2 4 ) Sel: 0.0010 ColGroup Usage:: PredCnt: 2 Matches Full: Partial: #1 (2 4 ) Sel: 0.0010 Access Path: index (skip-scan) SS sel: 0.001000 ANDV (#skips): 100.000000 SS io: 300.000000 vs. index scan io: 8455.000000 Skip Scan rejected Access Path: index (RangeScan) Index: TEST_IND_SELECTIVITY_IX1 resc_io: 1292.00 resc_cpu: 29410900 ix_sel: 0.100000 ix_sel_with_filters: 0.001000 ***** Logdef predicate Adjustment ****** Final IO cst 0.00 , CPU cst 50.00 ***** End Logdef Adjustment ****** Cost: 1292.01 Resp: 1292.01 Degree: 1 Best:: AccessPath: IndexRange Index: TEST_IND_SELECTIVITY_IX1 Cost: 1292.01 Degree: 1 Resp: 1292.01 Card: 1000.00 Bytes: 0 ***************************************
============ Plan Table ============ ----------------------------------------------------------------+-----------------------------------+ | Id | Operation | Name | Rows | Bytes | Cost | Time | ----------------------------------------------------------------+-----------------------------------+ | 0 | SELECT STATEMENT | | | | 1292 | | | 1 | SORT AGGREGATE | | 1 | 12 | | | | 2 | TABLE ACCESS BY INDEX ROWID | TEST_IND_SELECTIVITY | 1000 | 12K | 1292 | 00:00:07 | | 3 | INDEX RANGE SCAN | TEST_IND_SELECTIVITY_IX1| 1000 | | 292 | 00:00:02 | ----------------------------------------------------------------+-----------------------------------+ Predicate Information: ---------------------- 3 - access("COL1"=1 AND "COL3"=1) 3 - filter("COL3"=1)
select plan_table_output from table( dbms_xplan.display_cursor ( NULL, NULL, 'allstats')); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------------------------- SQL_ID gj6fuawjzpr51, child number 0 ------------------------------------- select /*+ index(test_ind_selectivity) gather_plan_statistics */ count(id) from test_ind_selectivity where col1 = 1 and col3 = 1 Plan hash value: 779399104 ------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.03 | 1296 | | 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.03 | 1296 | | 2 | TABLE ACCESS BY INDEX ROWID| TEST_IND_SELECTIVITY | 1 | 1000 | 1000 |00:00:00.01 | 1296 | |* 3 | INDEX RANGE SCAN | TEST_IND_SELECTIVITY_IX1 | 1 | 1000 | 1000 |00:00:00.01 | 296 | ------------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("COL1"=1 AND "COL3"=1) filter("COL3"=1)
What history has taught us is that such killer architectures do not exist, but that the optimal strategy (just like in nature) depends on which environment you find yourself in. Being an IT architect means rising above all these technologies, to see that big picture, and resisting the temptation to find a single solution/platform for all problems in the enterprise. They key is to understand the environment you live in, and design for it using a palette of technologies.Und das ist sicher eine ziemlich zeitlose Schlussfolgerung.
create function generator (n pls_integer) return sys.odcinumberlist pipelined is begin for i in 1 .. n loop pipe row (i); end loop; end; / select count(*) from table(generator(1e7));
select /*+ full(t) */ count(*) from dim_table t where t.col1 = 421220 AND t.col2 = 20 COUNT(*) ---------- 2841 ------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ------------------------------------------------------------------------------- | 0 | SELECT STATEMENT REMOTE| | 1 | 9 | 60397 (1)| | 1 | SORT AGGREGATE | | 1 | 9 | | |* 2 | TABLE ACCESS FULL | DIM_TABLE | 147 | 1323 | 60397 (1)| ------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("A1"."COL1"=421220 AND "A1"."COL2"=20) Note ----- - fully remote statement
select count(*) from fact_table f , dim_table d where f.col0 = d.col0 and d.col1 = 421220 AND d.col2 = 20 and f.col3 = '01.12.2011' COUNT(*) ---------- 13562 ---------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| ---------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 54 | 8 (0)| | 1 | SORT AGGREGATE | | 1 | 54 | | | 2 | NESTED LOOPS | | 24 | 1296 | 8 (0)| | 3 | REMOTE | DIM_TABLE | 2 | 78 | 4 (0)| | 4 | PARTITION RANGE SINGLE| | 12 | 180 | 2 (0)| |* 5 | INDEX RANGE SCAN | IDX_FACT_TABLE | 12 | 180 | 2 (0)| ---------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 5 - access("F"."COL0"="A"."COL0" AND "F"."COL3"=TO_DATE(' 2011-12-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss')) Remote SQL Information (identified by operation id): ---------------------------------------------------- 3 - SELECT "COL0","COL1","COL2" FROM "DIM_TABLE" "A" WHERE "COL1"=421220 AND "COL2"=20 (accessing 'DBL_XXX' )
select /*+ DRIVING_SITE(a) */ count(*) from fact_table f , dim_table d where f.col0 = d.col0 and d.col1 = 421220 AND d.col2 = 20 and f.col3 = '01.12.2011' --------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| --------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT REMOTE | | 1 | 38 | 395 (1)| | 1 | SORT AGGREGATE | | 1 | 38 | | | 2 | NESTED LOOPS | | 1703 | 64714 | 395 (1)| | 3 | TABLE ACCESS BY INDEX ROWID| DIM_TABLE | 147 | 2352 | 100 (0)| |* 4 | INDEX RANGE SCAN | IDX_DIM_TABLE | 147 | | 3 (0)| | 5 | REMOTE | FACT_TABLE | 12 | 264 | 2 (0)| --------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 4 - access("A1"."COL2"=20 AND "A1"."COL1"=421220) Remote SQL Information (identified by operation id): ---------------------------------------------------- 5 - SELECT "COL0","COL3" FROM "XXX"."FACT_TABLE" "A2" WHERE "COL3"=TO_DATE(' 2011-12-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "COL0"=:1 (accessing '!' )
select ... from a , b where a.id = b.id and a.id = 10
and b.id = 10
MERGE /*+ APPEND */ INTO FACT USING (SELECT A_DATE , ... FROM (SELECT DISTINCT A_DATE , ... FROM BASE WHERE A_DATE BETWEEN :B2 AND :B1 ) ) SOURCE ON ( some_conditions AND FACT.A_DATE = SOURCE.A_DATE ) WHEN MATCHED THEN UPDATE SET ... WHEN NOT MATCHED THEN INSERT ...
------------------------------------------------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib | ------------------------------------------------------------------------------------------------------------------------------------------------ | 0 | MERGE STATEMENT | | | | | 57703 (100)| | | | | | | | 1 | MERGE | FACT | | | | | | | | | | | | 2 | PX COORDINATOR | | | | | | | | | | | | | 3 | PX SEND QC (RANDOM) | :TQ10001 | 41430 | 8981K| | 57703 (7)| 00:13:04 | | | Q1,01 | P->S | QC (RAND) | | 4 | VIEW | | | | | | | | | Q1,01 | PCWP | | | 5 | HASH JOIN OUTER | | 41430 | 8981K| | 57703 (7)| 00:13:04 | | | Q1,01 | PCWP | | | 6 | BUFFER SORT | | | | | | | | | Q1,01 | PCWC | | | 7 | PX RECEIVE | | 41430 | 5502K| | 17408 (6)| 00:03:57 | | | Q1,01 | PCWP | | | 8 | PX SEND PARTITION (KEY)| :TQ10000 | 41430 | 5502K| | 17408 (6)| 00:03:57 | | | | S->P | PART (KEY) | | 9 | VIEW | | 41430 | 5502K| | 17408 (6)| 00:03:57 | | | | | | | 10 | SORT UNIQUE | | 41430 | 2022K| 6520K| 17408 (6)| 00:03:57 | | | | | | | 11 | FILTER | | | | | | | | | | | | | 12 | TABLE ACCESS FULL | BASE | 41430 | 2022K| | 16966 (6)| 00:03:51 | | | | | | | 13 | PX PARTITION RANGE ALL | | 895M| 71G| | 39789 (7)| 00:09:01 | 1 | 362 | Q1,01 | PCWC | | | 14 | TABLE ACCESS FULL | FACT | 895M| 71G| | 39789 (7)| 00:09:01 | 1 | 362 | Q1,01 | PCWP | | ------------------------------------------------------------------------------------------------------------------------------------------------
MERGE /*+ APPEND */ INTO FACT USING (SELECT DISTINCT A_DATE , ... FROM BASE WHERE A_DATE BETWEEN :B2 AND :B1 ) ) SOURCE ON ( some_conditions AND FACT.A_DATE = SOURCE.A_DATE ) WHEN MATCHED THEN UPDATE SET ... WHEN NOT MATCHED THEN INSERT ...
----------------------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Pstart| Pstop | TQ |IN-OUT| PQ Distrib | ----------------------------------------------------------------------------------------------------------------------------------------------- | 0 | MERGE STATEMENT | | 19294 | 5916K| | 43473 (1)| | | | | | | 1 | MERGE | FACT | | | | | | | | | | | 2 | PX COORDINATOR | | | | | | | | | | | | 3 | PX SEND QC (RANDOM) | :TQ10001 | 19294 | 4182K| | 43473 (1)| | | Q1,01 | P->S | QC (RAND) | | 4 | VIEW | | | | | | | | Q1,01 | PCWP | | | 5 | NESTED LOOPS OUTER | | 19294 | 4182K| | 43473 (1)| | | Q1,01 | PCWP | | | 6 | BUFFER SORT | | | | | | | | Q1,01 | PCWC | | | 7 | PX RECEIVE | | | | | | | | Q1,01 | PCWP | | | 8 | PX SEND ROUND-ROBIN | :TQ10000 | | | | | | | | S->P | RND-ROBIN | | 9 | VIEW | | 19294 | 2562K| | 4881 (9)| | | | | | | 10 | SORT UNIQUE | | 19294 | 942K| 3048K| 4881 (9)| | | | | | | 11 | FILTER | | | | | | | | | | | | 12 | TABLE ACCESS FULL | BASE | 19294 | 942K| | 4674 (9)| | | | | | | 13 | PARTITION RANGE ITERATOR | | 1 | 86 | | 0 (0)| KEY | KEY | Q1,01 | PCWP | | | 14 | TABLE ACCESS BY LOCAL INDEX ROWID| FACT | 1 | 86 | | 0 (0)| KEY | KEY | Q1,01 | PCWP | | | 15 | INDEX RANGE SCAN | PK_FACT | 1 | | | 0 (0)| KEY | KEY | Q1,01 | PCWP | | -----------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Pstart| Pstop | TQ |IN-OUT| PQ Distrib | ---------------------------------------------------------------------------------------------------------------------------- | 0 | MERGE STATEMENT | | 19294 | 5916K| 33548 (9)| | | | | | | 1 | MERGE | FACT | | | | | | | | | | 2 | PX COORDINATOR | | | | | | | | | | | 3 | PX SEND QC (RANDOM) | :TQ10002 | 19294 | 2562K| 33548 (9)| | | Q1,02 | P->S | QC (RAND) | | 4 | VIEW | | | | | | | Q1,02 | PCWP | | | 5 | FILTER | | | | | | | Q1,02 | PCWC | | | 6 | HASH JOIN OUTER BUFFERED| | 19294 | 2562K| 33548 (9)| | | Q1,02 | PCWP | | | 7 | BUFFER SORT | | | | | | | Q1,02 | PCWC | | | 8 | PX RECEIVE | | 19294 | 942K| 4674 (9)| | | Q1,02 | PCWP | | | 9 | PX SEND HASH | :TQ10000 | 19294 | 942K| 4674 (9)| | | | S->P | HASH | | 10 | TABLE ACCESS FULL | BASE | 19294 | 942K| 4674 (9)| | | | | | | 11 | PX RECEIVE | | 2237K| 183M| 28872 (9)| | | Q1,02 | PCWP | | | 12 | PX SEND HASH | :TQ10001 | 2237K| 183M| 28872 (9)| | | Q1,01 | P->P | HASH | | 13 | PX BLOCK ITERATOR | | 2237K| 183M| 28872 (9)| KEY | KEY | Q1,01 | PCWC | | | 14 | TABLE ACCESS FULL | FACT | 2237K| 183M| 28872 (9)| KEY | KEY | Q1,01 | PCWP | | ----------------------------------------------------------------------------------------------------------------------------