5. Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> create table t
2 as select decode( mod(rownum,2), 0, 'N', 'Y' ) flag1,
3 decode( mod(rownum,2), 0, 'Y', 'N' ) flag2, a.*
4 from all_objects a
5 /
Table created.
ops$tkyte%ORA11GR2> create index t_idx on t(flag1,flag2);
Index created.
ops$tkyte%ORA11GR2> begin
2 dbms_stats.gather_table_stats
3 ( user, 'T',
4 method_opt=>'for all indexed columns size 254' );
5 end;
6 /
PL/SQL procedure successfully completed.
6. Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> select 'select * from t', num_rows
2 from user_tables where table_name = 'T'
3 union all
4 select 'select * from t where flag1 = "N"', num_rows/2
5 from user_tables where table_name = 'T'
6 union all
7 select 'select * from t where flag2 = "N"', num_rows/2
8 from user_tables where table_name = 'T'
9 union all
10 select 'select * from t where flag1 = "N" and flag2 = "N"', num_rows/2/2
11 from user_tables where table_name = 'T';
'SELECT*FROMT' NUM_ROWS
------------------------------------------------- ----------
select * from t 72726
select * from t where flag1 = "N" 36363
select * from t where flag2 = "N" 36363
select * from t where flag1 = "N" and flag2 = "N" 18181.5
7. Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> set autotrace traceonly explain
ops$tkyte%ORA11GR2> select * from t where flag1='N';
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 36499 | 3635K| 301 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T | 36499 | 3635K| 301 (1)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("FLAG1"='N')
8. Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> select * from t where flag2='N';
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 36227 | 3608K| 301 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T | 36227 | 3608K| 301 (1)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("FLAG2"='N')
9. Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> select * from t where flag1='N' and flag2='N';
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 18181 | 1810K| 301 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T | 18181 | 1810K| 301 (1)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("FLAG2"='N' AND "FLAG1"='N')
10. Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> select /*+ gather_plan_statistics */ *
2 from t where flag1='N' and flag2='N';
no rows selected
11. Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> select * from
table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 0 |00:00:00.02 | 1080 |
|* 1 | TABLE ACCESS FULL| T | 1 | 18181 | 0 |00:00:00.02 | 1080 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(("FLAG2"='N' AND "FLAG1"='N'))
19 rows selected.
12. Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> select /*+ dynamic_sampling(t 3) */ * from t
where flag1='N' and flag2='N';
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6 | 612 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 6 | 612 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T_IDX | 6 | | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("FLAG1"='N' AND "FLAG2"='N')
Note
-----
- dynamic sampling used for this statement (level=2)
13. Wrong Plan => Wrong Cardinality
SELECT /* OPT_DYN_SAMP */ /*+ ALL_ROWS IGNORE_WHERE_CLAUSE
NO_PARALLEL(SAMPLESUB) opt_param('parallel_execution_enabled', 'false')
NO_PARALLEL_INDEX(SAMPLESUB) NO_SQL_TUNE */
NVL(SUM(C1),:"SYS_B_00"), NVL(SUM(C2),:"SYS_B_01"), NVL(SUM(C3),:"SYS_B_02")
FROM
(SELECT /*+ IGNORE_WHERE_CLAUSE NO_PARALLEL("T") FULL("T")
NO_PARALLEL_INDEX("T") */
:"SYS_B_03" AS C1,
CASE WHEN "T"."FLAG1"= :"SYS_B_04" AND "T"."FLAG2"=:"SYS_B_05"
THEN :"SYS_B_06"
ELSE :"SYS_B_07"
END AS C2,
CASE WHEN "T"."FLAG2"=:"SYS_B_08" AND "T"."FLAG1"=:"SYS_B_09“
THEN :"SYS_B_10"
ELSE :"SYS_B_11"
END AS C3
FROM "OPS$TKYTE"."T"
SAMPLE BLOCK (:"SYS_B_12" , :"SYS_B_13") SEED (:"SYS_B_14") "T") SAMPLESUB
15. Disabling/Hinting is bad
Goal is to get correct cardinality
If you can hint it, you can baseline
it. If you baseline it – it will use that
plan, and that plan can evolve over
time (if we let it)