SlideShare a Scribd company logo
Why do we gather
statistics?
“Cardinality”
“Wrong Cardinality
=> Wrong Plan”
“Wrong Plan =>
Wrong Cardinality”
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.
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
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')
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')
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')
Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> select /*+ gather_plan_statistics */ *
2 from t where flag1='N' and flag2='N';
no rows selected
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.
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)
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
X
• X
• X
• X
• X
• X
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)

More Related Content

PPTX
5 Cool Things About SQL
PPTX
A few things about the Oracle optimizer - 2013
PPTX
Controller Implementation in Verilog
TXT
Park script
PDF
Oracle Diagnostics : Explain Plans (Simple)
PDF
Oracle b tree index internals - rebuilding the thruth
PDF
ActiveReports Document
PPT
Do You Know The 11g Plan?
5 Cool Things About SQL
A few things about the Oracle optimizer - 2013
Controller Implementation in Verilog
Park script
Oracle Diagnostics : Explain Plans (Simple)
Oracle b tree index internals - rebuilding the thruth
ActiveReports Document
Do You Know The 11g Plan?

Similar to Cardinality and the Optimizer (20)

PDF
Adaptive Query Optimization
PDF
Demystifying cost based optimization
PDF
Query optimizer vivek sharma
PDF
Managing Statistics for Optimal Query Performance
PDF
Understanding Optimizer-Statistics-for-Developers
PDF
Oracle statistics by example
DOCX
10053 - null is not nothing
PPT
Metadata Matters
PDF
12c SQL Plan Directives
PPTX
Five more things about Oracle SQL and PLSQL
PPTX
Introduction to oracle optimizer
PPTX
CBO Basics: Cardinality
PPT
sqltuningcardinality1(1).ppt
PPTX
Embarcadero In Search of Plan Stability Part 1 Webinar Slides
PPTX
PLSQL Practices
PDF
Oracle Diagnostics : Joins - 1
PPTX
Oracle Database 12c features for DBA
PPTX
Writing efficient sql
PDF
Riyaj: why optimizer_hates_my_sql_2010
PPT
Dbms plan - A swiss army knife for performance engineers
Adaptive Query Optimization
Demystifying cost based optimization
Query optimizer vivek sharma
Managing Statistics for Optimal Query Performance
Understanding Optimizer-Statistics-for-Developers
Oracle statistics by example
10053 - null is not nothing
Metadata Matters
12c SQL Plan Directives
Five more things about Oracle SQL and PLSQL
Introduction to oracle optimizer
CBO Basics: Cardinality
sqltuningcardinality1(1).ppt
Embarcadero In Search of Plan Stability Part 1 Webinar Slides
PLSQL Practices
Oracle Diagnostics : Joins - 1
Oracle Database 12c features for DBA
Writing efficient sql
Riyaj: why optimizer_hates_my_sql_2010
Dbms plan - A swiss army knife for performance engineers
Ad

More from Connor McDonald (20)

PDF
Flashback ITOUG
PDF
Sangam 19 - PLSQL still the coolest
PDF
Sangam 19 - Analytic SQL
PDF
UKOUG - 25 years of hints and tips
PDF
Sangam 19 - Successful Applications on Autonomous
PDF
Sangam 2019 - The Latest Features
PDF
UKOUG 2019 - SQL features
PDF
APEX tour 2019 - successful development with autonomous
PDF
APAC Groundbreakers 2019 - Perth/Melbourne
PDF
OOW19 - Flashback, not just for DBAs
PDF
OOW19 - Read consistency
PDF
OOW19 - Slower and less secure applications
PDF
OOW19 - Killing database sessions
PDF
OOW19 - Ten Amazing SQL features
PDF
Latin America Tour 2019 - 18c and 19c featues
PDF
Latin America tour 2019 - Flashback
PDF
Latin America Tour 2019 - 10 great sql features
PDF
Latin America Tour 2019 - pattern matching
PDF
Latin America Tour 2019 - slow data and sql processing
PDF
ANSI vs Oracle language
Flashback ITOUG
Sangam 19 - PLSQL still the coolest
Sangam 19 - Analytic SQL
UKOUG - 25 years of hints and tips
Sangam 19 - Successful Applications on Autonomous
Sangam 2019 - The Latest Features
UKOUG 2019 - SQL features
APEX tour 2019 - successful development with autonomous
APAC Groundbreakers 2019 - Perth/Melbourne
OOW19 - Flashback, not just for DBAs
OOW19 - Read consistency
OOW19 - Slower and less secure applications
OOW19 - Killing database sessions
OOW19 - Ten Amazing SQL features
Latin America Tour 2019 - 18c and 19c featues
Latin America tour 2019 - Flashback
Latin America Tour 2019 - 10 great sql features
Latin America Tour 2019 - pattern matching
Latin America Tour 2019 - slow data and sql processing
ANSI vs Oracle language
Ad

Recently uploaded (20)

PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Zenith AI: Advanced Artificial Intelligence
PDF
Hindi spoken digit analysis for native and non-native speakers
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
From MVP to Full-Scale Product A Startup’s Software Journey.pdf
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PDF
Accuracy of neural networks in brain wave diagnosis of schizophrenia
PDF
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Getting Started with Data Integration: FME Form 101
PPTX
SOPHOS-XG Firewall Administrator PPT.pptx
PPTX
Group 1 Presentation -Planning and Decision Making .pptx
PDF
DP Operators-handbook-extract for the Mautical Institute
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
A Presentation on Touch Screen Technology
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
A novel scalable deep ensemble learning framework for big data classification...
PPTX
A Presentation on Artificial Intelligence
PDF
A comparative study of natural language inference in Swahili using monolingua...
PDF
MIND Revenue Release Quarter 2 2025 Press Release
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Zenith AI: Advanced Artificial Intelligence
Hindi spoken digit analysis for native and non-native speakers
Building Integrated photovoltaic BIPV_UPV.pdf
From MVP to Full-Scale Product A Startup’s Software Journey.pdf
NewMind AI Weekly Chronicles - August'25-Week II
Accuracy of neural networks in brain wave diagnosis of schizophrenia
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Getting Started with Data Integration: FME Form 101
SOPHOS-XG Firewall Administrator PPT.pptx
Group 1 Presentation -Planning and Decision Making .pptx
DP Operators-handbook-extract for the Mautical Institute
Unlocking AI with Model Context Protocol (MCP)
A Presentation on Touch Screen Technology
Agricultural_Statistics_at_a_Glance_2022_0.pdf
A novel scalable deep ensemble learning framework for big data classification...
A Presentation on Artificial Intelligence
A comparative study of natural language inference in Swahili using monolingua...
MIND Revenue Release Quarter 2 2025 Press Release

Cardinality and the Optimizer

  • 1. Why do we gather statistics?
  • 4. “Wrong Plan => Wrong Cardinality”
  • 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
  • 14. X • X • X • X • X • X
  • 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)