getting the right cardinality thomas kyte
TRANSCRIPT
![Page 1: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/1.jpg)
<Insert Picture Here>
Getting the Right Cardinality
Thomas Kytehttp://asktom.oracle.com/
![Page 2: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/2.jpg)
Why do we gather statistics?
![Page 3: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/3.jpg)
“Cardinality”
![Page 4: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/4.jpg)
“Wrong Plan => Wrong Cardinality”
![Page 5: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/5.jpg)
“Wrong Cardinality => Wrong Plan”
![Page 6: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/6.jpg)
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.
![Page 7: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/7.jpg)
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
![Page 8: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/8.jpg)
Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> set autotrace traceonly explain
ops$tkyte%ORA11GR2> select * from t where flag1='N';
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| 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')
![Page 9: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/9.jpg)
Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> select * from t where flag2='N';
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| 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')
![Page 10: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/10.jpg)
Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> select * from t where flag1='N' and flag2='N';
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| 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')
![Page 11: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/11.jpg)
Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> select /*+ gather_plan_statistics */ *
2 from t where flag1='N' and flag2='N';
no rows selected
![Page 12: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/12.jpg)
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.
![Page 13: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/13.jpg)
Wrong Plan => Wrong Cardinality
ops$tkyte%ORA11GR2> select /*+ dynamic_sampling(t 3) */ * from t where flag1='N' and flag2='N';
Execution Plan
----------------------------------------------------------
Plan hash value: 470836197
-------------------------------------------------------------------------------------
| 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)
![Page 14: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/14.jpg)
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
![Page 15: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/15.jpg)
Small Change – but think about it…
ops$tkyte%ORA11GR2> create table t
2 as
3 select substr(object_name, 1, 1 ) str, all_objects.*
4 from all_objects
5 order by dbms_random.random;
Table created.
ops$tkyte%ORA11GR2> create index t_idx on t(str,object_name);
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 estimate_percent=>100 );
6 end;
7 /
PL/SQL procedure successfully completed.
![Page 16: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/16.jpg)
ops$tkyte%ORA11GR2> select count(subobject_name) from t t1 where str = 'T';
…
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 19 | 296 (0)| 00:00:04 |
| 1 | SORT AGGREGATE | | 1 | 19 | | |
| 2 | TABLE ACCESS BY INDEX ROWID| T | 292 | 5548 | 296 (0)| 00:00:04 |
|* 3 | INDEX RANGE SCAN | T_IDX | 292 | | 4 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Small Change – but think about it…
![Page 17: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/17.jpg)
ops$tkyte%ORA11GR2> insert into t
2 select 'T', all_objects.*
3 from all_objects
4 where rownum <= 1;
1 row created.
ops$tkyte%ORA11GR2> begin
2 dbms_stats.gather_table_stats
3 ( user, 'T',
4 method_opt => 'for all indexed columns size 254',
5 estimate_percent=>100 );
6 end;
7 /
PL/SQL procedure successfully completed.
Small Change – but think about it…
![Page 18: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/18.jpg)
ops$tkyte%ORA11GR2> select count(subobject_name) from t t2 where str = 'T';
…
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 19 | 297 (1)| 00:00:04 |
| 1 | SORT AGGREGATE | | 1 | 19 | | |
|* 2 | TABLE ACCESS FULL| T | 293 | 5567 | 297 (1)| 00:00:04 |
---------------------------------------------------------------------------
Small Change – but think about it…
![Page 19: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/19.jpg)
Statistics Basics
![Page 20: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/20.jpg)
Things Change over Time
• In 10g and before, it was very common to “program” our statistics gathering– Unique set of inputs for each and every table and index
• In 11g, you should as often as possible allow everything except the segment name and DOP to default– Why is this?
• However…
![Page 21: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/21.jpg)
21
You are being WATCHED!
ops$tkyte%ORA11GR2> create table t 2 as 3 select a.*, 4 case when rownum < 500 5 then 1 6 else 99 7 end some_status 8 from all_objects a 9 /Table created.
![Page 22: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/22.jpg)
22
You are being WATCHED!
ops$tkyte%ORA11GR2> begin 2 dbms_stats.gather_table_stats(user,'T'); 3 end; 4 /
PL/SQL procedure successfully completed.
![Page 23: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/23.jpg)
23
You are being WATCHED!
ops$tkyte%ORA11GR2> select histogram 2 from user_tab_cols 3 where table_name = 'T' 4 and column_name = 'SOME_STATUS';
HISTOGRAM---------------NONE
![Page 24: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/24.jpg)
24
You are being WATCHED!
ops$tkyte%ORA11GR2> create index t_idx on t(some_status);
Index created.
![Page 25: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/25.jpg)
25
You are being WATCHED!
ops$tkyte%ORA11GR2> select * from t where some_status = 99;
Execution Plan----------------------------------------------------------Plan hash value: 1601196873
--------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 36115 | 3526K| 300 (1)| 00:00:04 ||* 1 | TABLE ACCESS FULL| T | 36115 | 3526K| 300 (1)| 00:00:04 |--------------------------------------------------------------------------
![Page 26: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/26.jpg)
26
You are being WATCHED!
ops$tkyte%ORA11GR2> begin 2 dbms_stats.gather_table_stats( user, 'T' ); 3 end; 4 /
PL/SQL procedure successfully completed.
![Page 27: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/27.jpg)
27
You are being WATCHED!
ops$tkyte%ORA11GR2> select histogram 2 from user_tab_cols 3 where table_name = 'T' 4 and column_name = 'SOME_STATUS';
HISTOGRAM---------------FREQUENCY
![Page 28: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/28.jpg)
28
You are being WATCHED!
ops$tkyte%ORA11GR2> select * from t where some_status = 1;
Execution Plan----------------------------------------------------------Plan hash value: 470836197
--------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time --------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 539 | 53900 | 10 (0)| 00:00| 1 | TABLE ACCESS BY INDEX ROWID| T | 539 | 53900 | 10 (0)| 00:00|* 2 | INDEX RANGE SCAN | T_IDX | 539 | | 2 (0)| 00:00--------------------------------------------------------------------------------
![Page 29: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/29.jpg)
29
You are being WATCHED!
ops$tkyte%ORA11GR2> select * from t where some_status = 99;
Execution Plan----------------------------------------------------------Plan hash value: 1601196873
--------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 71683 | 7000K| 300 (1)| 00:00:04 ||* 1 | TABLE ACCESS FULL| T | 71683 | 7000K| 300 (1)| 00:00:04 |--------------------------------------------------------------------------
![Page 30: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/30.jpg)
30
Index Statistics – little known fact
ops$tkyte%ORA11GR2> create table t
2 as
3 select *
4 from all_objects
5 /
Table created.
ops$tkyte%ORA11GR2> create index t_idx on t(object_id);
Index created.
ops$tkyte%ORA11GR2> select num_rows, sample_size, last_analyzed
2 from user_indexes
3 where index_name = 'T_IDX';
NUM_ROWS SAMPLE_SIZE LAST_ANAL
---------- ----------- ---------
72726 72726 17-JUL-12
![Page 31: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/31.jpg)
Other Ways to Get Statistics
![Page 32: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/32.jpg)
Other ways to get statistics
• DBMS_STATS.SET_xxx– If you know the statistics, just tell us
• DBMS_STATS.COPY_xxx– If you have something representative, just use to them to start
• Dynamic Sampling…• SQL Profiles• Extended Statistics• Cardinality Feedback• Cardinality Hint
![Page 33: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/33.jpg)
Dynamic Sampling
• http://www.oracle.com/technetwork/issue-archive/2009/09-jan/o19asktom-086775.html– Google: site:www.oracle.com kyte dynamic
• Already demonstrated
• Levels– 2 – sample any unanalyzed table during hard parse– 3 – same as 2 but add “sample during guess” for single
column guesses– 4 – same as 3 but add “sample during guess” for multi-
column guesses
![Page 34: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/34.jpg)
SQL Profiles
• Analyzing a query• Stores better estimated cardinalities – Gets these by using your workload against your data– Important to be done in the right environment– Are just statistics really, so yes, they can go stale
• Applied at hard parse time
![Page 35: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/35.jpg)
SQL Profiles
ops$tkyte@ORA11G> create or replace procedure p
2 as
3 cursor c1
4 is
5 select object_id, object_name
6 from sqlprof
7 order by object_id;
9 l_object_id sqlprof.object_id%type;
10 l_object_name sqlprof.object_name%type;
11 begin
12 open c1;
13 for i in 1 .. 10
14 loop
15 fetch c1 into l_object_id, l_object_name;
16 exit when c1%notfound;
17 -- ....
18 end loop;
19 end;
20 /
Procedure created.
![Page 36: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/36.jpg)
SQL Profiles
SELECT OBJECT_ID, OBJECT_NAME FROM SQLPROF ORDER BY OBJECT_ID
call count cpu elapsed query current rows
------- ------ -------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0
Execute 1 0.00 0.00 0 0 0
Fetch 10 0.07 0.10 659 0 10
------- ------ -------- ---------- ---------- ---------- ----------
total 12 0.07 0.10 659 0 10
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 410 (recursive depth: 1)
Rows Row Source Operation
------- ---------------------------------------------------
10 SORT ORDER BY (cr=659 pr=0 pw=0 time=101152 us)
47487 TABLE ACCESS FULL SQLPROF (cr=659 pr=0 pw=0 time=47604 us)
![Page 37: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/37.jpg)
SQL Profiles
ops$tkyte@ORA11G> declare
2 l_sql_id v$sql.sql_id%type;
3 begin
4 select sql_id into l_sql_id
5 from v$sql
6 where sql_text = 'SELECT OBJECT_ID, OBJECT_NAME
FROM SQLPROF ORDER BY OBJECT_ID';
7 dbms_output.put_line(
8 sys.dbms_sqltune.create_tuning_task 9 ( sql_id => l_sql_id,
10 task_name => 'sqlprof_query' ) || ' in place...' );
11 dbms_sqltune.execute_tuning_task
12 ( task_name => 'sqlprof_query' );
13 end;
14 /
PL/SQL procedure successfully completed.
![Page 38: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/38.jpg)
SQL Profiles
ops$tkyte@ORA11G> SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK( 'sqlprof_query')
2 FROM DUAL;
DBMS_SQLTUNE.REPORT_TUNING_TASK('SQLPROF_QUERY')
--------------------------------------------------------------------------------
GENERAL INFORMATION SECTION
…
-------------------------------------------------------------------------------
SQL ID : 3zfpa86satsm3
SQL Text: SELECT OBJECT_ID, OBJECT_NAME FROM SQLPROF ORDER BY OBJECT_ID
-------------------------------------------------------------------------------
FINDINGS SECTION (1 finding)
-------------------------------------------------------------------------------
1- SQL Profile Finding (see explain plans section below)
--------------------------------------------------------
A potentially better execution plan was found for this statement.
Recommendation (estimated benefit: 99.45%)
------------------------------------------
Consider accepting the recommended SQL profile.
execute :profile_name := dbms_sqltune.accept_sql_profile(task_name =>
'sqlprof_query')
![Page 39: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/39.jpg)
SQL Profiles
1- Original With Adjusted Cost
------------------------------
Plan hash value: 1044598349
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time|
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 47487 | 1391K| | 546 (3)| 00:00:07 |
| 1 | SORT ORDER BY | | 47487 | 1391K| 3736K| 546 (3)| 00:00:07 |
| 2 | TABLE ACCESS FULL| SQLPROF | 47487 | 1391K| | 151 (2)| 00:00:02 |
--------------------------------------------------------------------------------------
2- Using SQL Profile
--------------------
Plan hash value: 337606071
------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)|Time | ------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 10 | 300 | 3 (0)|00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| SQLPROF | 47487 | 1391K| 3 (0)|00:00:01 |
| 2 | INDEX FULL SCAN | SQLPROF_PK | 10 | | 2 (0)|00:00:01 |
------------------------------------------------------------------------------------------
![Page 40: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/40.jpg)
Extended Statistics
• https://blogs.oracle.com/optimizer/entry/extended_statistics• In fact, https://blogs.oracle.com/optimizer should be
mandatory reading!
• Create statistics on sets of columns (correlated columns)
• Create statistics on expressions (functions)
![Page 41: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/41.jpg)
41
Extended Statistics
ops$tkyte%ORA11GR2> create table t 2 as 3 select * 4 from all_objects;Table created. ops$tkyte%ORA11GR2> create index t_idx on t(owner,object_type);Index created.
ops$tkyte%ORA11GR2> exec dbms_stats.gather_table_stats( user, 'T', method_opt=>'for all columns size 254' );
PL/SQL procedure successfully completed.
![Page 42: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/42.jpg)
42
Extended Statistics
ops$tkyte%ORA11GR2> set autotrace traceonly explainops$tkyte%ORA11GR2> select * from t where owner = 'PUBLIC' and object_type = 'JAVA CLASS';
Execution Plan----------------------------------------------------------Plan hash value: 1601196873
--------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 9015 | 853K| 290 (1)| 00:00:04 ||* 1 | TABLE ACCESS FULL| T | 9015 | 853K| 290 (1)| 00:00:04 |--------------------------------------------------------------------------
Predicate Information (identified by operation id):---------------------------------------------------
1 - filter("OBJECT_TYPE"='JAVA CLASS' AND "OWNER"='PUBLIC')
![Page 43: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/43.jpg)
43
Extended Statistics
ops$tkyte%ORA11GR2> select dbms_stats.create_extended_stats( user, 'T', '(owner,object_type)' ) x from dual;
X--------------------------------------------------SYS_STUXJ8K0YTS_5QD1O0PEA514IY
ops$tkyte%ORA11GR2> exec dbms_stats.gather_table_stats( user, 'T', method_opt=>'for all columns size 254' );
PL/SQL procedure successfully completed.
![Page 44: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/44.jpg)
44
Extended Statistics
ops$tkyte%ORA11GR2> set autotrace traceonly explainops$tkyte%ORA11GR2> select * from t where owner = 'PUBLIC' and object_type = 'JAVA CLASS';
Execution Plan----------------------------------------------------------Plan hash value: 470836197
-------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 7 | 763 | 2 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| T | 7 | 763 | 2 (0)| 00:00:01 ||* 2 | INDEX RANGE SCAN | T_IDX | 7 | | 1 (0)| 00:00:01 |-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):---------------------------------------------------
2 - access("OWNER"='PUBLIC' AND "OBJECT_TYPE"='JAVA CLASS')
![Page 45: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/45.jpg)
Extended Statistics
• See https://blogs.oracle.com/optimizer/entry/how_do_i_know_what_extended_statistics_are_needed_for_a_given_workload for how to have these column groups automatically built for you
• Extended statistics on functions done exactly the same
![Page 46: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/46.jpg)
46
Extended Statistics
ops$tkyte%ORA11GR2> create table t 2 as 3 select rownum a, -rownum b, all_objects.* 4 from all_objects;
Table created.
ops$tkyte%ORA11GR2> exec dbms_stats.gather_table_stats( user, 'T', method_opt=>'for all columns size 254' );
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR2> select 0.05 * count(*) from t;
0.05*COUNT(*)------------- 3635.15
![Page 47: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/47.jpg)
47
Extended Statistics
ops$tkyte%ORA11GR2> set autotrace traceonly explainops$tkyte%ORA11GR2> select * from t where (a+b)/2 > 50;
Execution Plan----------------------------------------------------------Plan hash value: 1601196873
--------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 3635 | 383K| 321 (1)| 00:00:04 ||* 1 | TABLE ACCESS FULL| T | 3635 | 383K| 321 (1)| 00:00:04 |--------------------------------------------------------------------------
Predicate Information (identified by operation id):---------------------------------------------------
1 - filter(("A"+"B")/2>50)
![Page 48: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/48.jpg)
48
Extended Statistics
ops$tkyte%ORA11GR2> set autotrace offops$tkyte%ORA11GR2> ops$tkyte%ORA11GR2> select dbms_stats.create_extended_stats( user, 'T', '((a+b)/2)' ) x from dual;
X--------------------------------------------------SYS_STUS9G#61NMFNG0T#HK9W8062Y
ops$tkyte%ORA11GR2> exec dbms_stats.gather_table_stats( user, 'T', method_opt=>'for all columns size 254' );
PL/SQL procedure successfully completed.
![Page 49: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/49.jpg)
49
Extended Statistics
ops$tkyte%ORA11GR2> set autotrace traceonly explainops$tkyte%ORA11GR2> select * from t where (a+b)/2 > 50;
Execution Plan----------------------------------------------------------Plan hash value: 1601196873
--------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 110 | 320 (1)| 00:00:04 ||* 1 | TABLE ACCESS FULL| T | 1 | 110 | 320 (1)| 00:00:04 |--------------------------------------------------------------------------
Predicate Information (identified by operation id):---------------------------------------------------
1 - filter(("A"+"B")/2>50)
![Page 50: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/50.jpg)
50
Cardinality Feedback
ops$tkyte%ORA11GR2> create or replace type str2tblType as table of varchar2(30) 2 /Type created.
ops$tkyte%ORA11GR2> create or replace function str2tbl( p_str in varchar2, p_delim in varchar2 default ',' ) return str2tblType 2 PIPELINED 3 as 4 l_str long default p_str || p_delim; 5 l_n number; 6 begin 7 loop 8 l_n := instr( l_str, p_delim ); 9 exit when (nvl(l_n,0) = 0); 10 pipe row( ltrim(rtrim(substr(l_str,1,l_n-1))) ); 11 l_str := substr( l_str, l_n+1 ); 12 end loop; 13 return; 14 end; 15 /Function created.
![Page 51: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/51.jpg)
51
Cardinality Feedback
ops$tkyte%ORA11GR2> var in_list varchar2(255)ops$tkyte%ORA11GR2> exec :in_list := 'DBMS_PIPE,DBMS_OUTPUT,UTL_FILE';
PL/SQL procedure successfully completed.
ops$tkyte%ORA11GR2> ops$tkyte%ORA11GR2> with data as 2 ( select /*+ materialize */ distinct * 3 from TABLE(cast( str2tbl( :in_list ) as str2tblType) ) t 4 ) 5 select * from data;
COLUMN_VALUE------------------------------DBMS_PIPEDBMS_OUTPUTUTL_FILE
![Page 52: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/52.jpg)
52
Cardinality Feedback
---------------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|---------------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | | 33 (100)|| 1 | TEMP TABLE TRANSFORMATION | | | | || 2 | LOAD AS SELECT | | | | || 3 | HASH UNIQUE | | 8168 | 16336 | 30 (4)|| 4 | COLLECTION ITERATOR PICKLER FETCH| STR2TBL | 8168 | 16336 | 29 (0)|| 5 | VIEW | | 8168 | 135K| 3 (0)|| 6 | TABLE ACCESS FULL | SYS_TEMP_0FD9D660F_52718F2 | 8168 | 16336 | 3 (0)|---------------------------------------------------------------------------------------------------------
20 rows selected.
![Page 53: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/53.jpg)
53
Cardinality Feedback
---------------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|---------------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | | 33 (100)|| 1 | TEMP TABLE TRANSFORMATION | | | | || 2 | LOAD AS SELECT | | | | || 3 | HASH UNIQUE | | 8168 | 16336 | 30 (4)|| 4 | COLLECTION ITERATOR PICKLER FETCH| STR2TBL | 8168 | 16336 | 29 (0)|| 5 | VIEW | | 3 | 51 | 3 (0)|| 6 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6610_52718F2 | 3 | 6 | 3 (0)|---------------------------------------------------------------------------------------------------------
Note----- - cardinality feedback used for this statement
24 rows selected.
![Page 54: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/54.jpg)
54
Cardinality Feedback
ops$tkyte%ORA11GR2> create table t 2 as 3 select * from all_objects;
Table created.
ops$tkyte%ORA11GR2> ops$tkyte%ORA11GR2> create index t_idx on t(object_name);
Index created.
ops$tkyte%ORA11GR2> ops$tkyte%ORA11GR2> exec dbms_stats.gather_table_stats(user,'T');
PL/SQL procedure successfully completed.
![Page 55: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/55.jpg)
55
Cardinality Feedback
ops$tkyte%ORA11GR2> with data as 2 ( select /*+ materialize */ distinct * 3 from TABLE(cast( str2tbl( :in_list ) as str2tblType) ) t 4 ) 5 select t.object_id, t.object_name from data, t 6 where t.object_name = data.column_value;
OBJECT_ID OBJECT_NAME---------- ------------------------------ 4972 DBMS_OUTPUT 4973 DBMS_OUTPUT 4982 UTL_FILE 4983 UTL_FILE 7929 DBMS_PIPE 7930 DBMS_PIPE 8842 DBMS_OUTPUT 11587 UTL_FILE 11626 DBMS_PIPE 72606 UTL_FILE
10 rows selected.
![Page 56: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/56.jpg)
56
Cardinality Feedback
---------------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Cost (%CPU)| Time---------------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | 324 (100)|| 1 | TEMP TABLE TRANSFORMATION | | | || 2 | LOAD AS SELECT | | | || 3 | HASH UNIQUE | | 8168 | 30 (4)| 00:00:01| 4 | COLLECTION ITERATOR PICKLER FETCH| STR2TBL | 8168 | 29 (0)| 00:00:01|* 5 | HASH JOIN | | 13630 | 294 (1)| 00:00:04| 6 | VIEW | | 8168 | 3 (0)| 00:00:01| 7 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6611_52718F2 | 8168 | 3 (0)| 00:00:01| 8 | TABLE ACCESS FULL | T | 72708 | 290 (1)| 00:00:04---------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):---------------------------------------------------
5 - access("T"."OBJECT_NAME"="DATA"."COLUMN_VALUE")
28 rows selected.
![Page 57: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/57.jpg)
57
Cardinality Feedback
---------------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Cost (%CPU)| Time---------------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | 42 (100)|| 1 | TEMP TABLE TRANSFORMATION | | | || 2 | LOAD AS SELECT | | | || 3 | HASH UNIQUE | | 8168 | 30 (4)| 00:00:01| 4 | COLLECTION ITERATOR PICKLER FETCH| STR2TBL | 8168 | 29 (0)| 00:00:01| 5 | NESTED LOOPS | | | || 6 | NESTED LOOPS | | 5 | 12 (0)| 00:00:01| 7 | VIEW | | 3 | 3 (0)| 00:00:01| 8 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6612_52718F2 | 3 | 3 (0)| 00:00:01|* 9 | INDEX RANGE SCAN | T_IDX | 2 | 2 (0)| 00:00:01| 10 | TABLE ACCESS BY INDEX ROWID | T | 2 | 3 (0)| 00:00:01---------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):---------------------------------------------------
9 - access("T"."OBJECT_NAME"="DATA"."COLUMN_VALUE")
Note----- - cardinality feedback used for this statement
34 rows selected.
![Page 58: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/58.jpg)
58
Cardinality Hint
ops$tkyte%ORA11GR2> with data as 2 ( select * 3 from TABLE(cast( str2tbl( :in_list ) as str2tblType) ) t 4 ) 5 select t.object_id, t.object_name 6 from data, t 7 where t.object_name = data.column_value;
OBJECT_ID OBJECT_NAME---------- ------------------------------ 4972 DBMS_OUTPUT 4973 DBMS_OUTPUT 4982 UTL_FILE 4983 UTL_FILE 7929 DBMS_PIPE 7930 DBMS_PIPE 8842 DBMS_OUTPUT 11587 UTL_FILE 11626 DBMS_PIPE 72606 UTL_FILE10 rows selected.
![Page 59: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/59.jpg)
59
Cardinality Hint
----------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |----------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | | 320 (100)| ||* 1 | HASH JOIN | | 13630 | 425K| 320 (1)| 00:00:04 || 2 | COLLECTION ITERATOR PICKLER FETCH| STR2TBL | 8168 | 16336 | 29 (0)| 00:00:01 || 3 | TABLE ACCESS FULL | T | 72708 | 2130K| 290 (1)| 00:00:04 |----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):---------------------------------------------------
1 - access("T"."OBJECT_NAME"=VALUE(KOKBF$))
22 rows selected.
![Page 60: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/60.jpg)
60
Cardinality Hint
ops$tkyte%ORA11GR2> with data as 2 ( select /*+ cardinality( t, 10 ) */ * 3 from TABLE(cast( str2tbl( :in_list ) as str2tblType) ) t 4 ) 5 select t.object_id, t.object_name 6 from data, t 7 where t.object_name = data.column_value;
OBJECT_ID OBJECT_NAME---------- ------------------------------ 4972 DBMS_OUTPUT 4973 DBMS_OUTPUT 4982 UTL_FILE 4983 UTL_FILE 7929 DBMS_PIPE 7930 DBMS_PIPE 8842 DBMS_OUTPUT 11587 UTL_FILE 11626 DBMS_PIPE 72606 UTL_FILE10 rows selected.
![Page 61: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/61.jpg)
61
Cardinality Hint
-----------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-----------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | | | 59 (100)| || 1 | NESTED LOOPS | | | | | || 2 | NESTED LOOPS | | 17 | 544 | 59 (0)| 00:00:01 || 3 | COLLECTION ITERATOR PICKLER FETCH| STR2TBL | 10 | 20 | 29 (0)| 00:00:01 ||* 4 | INDEX RANGE SCAN | T_IDX | 2 | | 2 (0)| 00:00:01 || 5 | TABLE ACCESS BY INDEX ROWID | T | 2 | 60 | 3 (0)| 00:00:01 |-----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):---------------------------------------------------
4 - access("T"."OBJECT_NAME"=VALUE(KOKBF$))
25 rows selected.
![Page 62: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/62.jpg)
When all else Fails…
![Page 63: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/63.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.85
If you can hint it, baseline it
Its not always possible to add hints to third party applications Hints can be extremely difficult to manage over time Once added never removed
Alternative approach to hints
Solution Use SQL Plan Management (SPM) Influence the execution plan without adding hints directly to queries SPM available in EE, no additional options required
![Page 64: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/64.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.86
If you can hint it, baseline itSQL Plan Management
Parse
HJ
HJ
GB
Plan history
Plan baseline
Execute
Plan Acceptable
HJ
HJ
GB
Users
![Page 65: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/65.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.87
If you can hint it, baseline itSQL Plan Management
Parse
NL
NL
GB
Plan history
Plan baseline
HJ
HJ
GB
Users
NL
NL
GB
![Page 66: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/66.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.88
If you can hint it, baseline itSQL Plan Management
Parse
Plan history
Plan baseline
Execute
Plan Acceptable
HJ
HJ
GB
Users
NL
NL
GB
HJ
HJ
GB
![Page 67: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/67.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.89
Influence execution plan without adding hints
Simple two table join between the SALES and PRODUCTS tables
Example Overview
Group By
HASH JOIN
TABLE ACCESS SALES
TABLE ACCESS PRODUCTS
Group By
HASH JOIN
TABLE ACCESS SALESINDEX RANGE SCAN
PROD_SUPP_ID_INDX
Current Plan Desired Plan
![Page 68: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/68.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.90
Influence execution plan without adding hintsStep 1. Execute the non-hinted SQL statement
![Page 69: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/69.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.91
Influence execution plan without adding hintsDefault plan is uses full table scans followed by a hash join
![Page 70: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/70.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.92
Influence execution plan without adding hintsStep 2. Find the SQL_ID for the non-hinted statement in V$SQL
![Page 71: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/71.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.93
Influence execution plan without adding hintsStep 3. Create a SQL plan baseline for the non-hinted SQL statement
![Page 72: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/72.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.94
Influence execution plan without adding hintsStep 4. Captured Plan is not our desired plan so it should be disabled
![Page 73: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/73.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.95
Influence execution plan without adding hintsStep 5. Modify the SQL statement to use the hint(s) & execute it
![Page 74: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/74.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.96
Influence execution plan without adding hintsStep 6. Find SQL_ID & PLAN_HASH_VALUE for hinted SQL stmt
![Page 75: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/75.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.97
Influence execution plan without adding hintsStep 7. Associate hinted plan with original SQL stmt’s SQL HANDLE
Sql_id & plan_hash_value belong to hinted statement
sql_handle is for the non-hinted statement
![Page 76: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/76.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.98
Influence execution plan without adding hintsStep 8. Confirm SQL stmt has two plans in it’s baseline
Hinted plan only accepted plan for non-hinted SQL stmt
![Page 77: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/77.jpg)
Copyright © 2012, Oracle and/or its affiliates. All rights reserved.99
Influence execution plan without adding hintsStep 9. Confirm hinted plan is being used
Non-hinted SQL text but it is using the plan hash value for the hinted stmt
Note section also confirms SQL plan baseline used for stmt
![Page 78: Getting the Right Cardinality Thomas Kyte](https://reader035.vdocuments.net/reader035/viewer/2022070410/56649ed25503460f94be17c6/html5/thumbnails/78.jpg)
<Insert Picture Here>
Getting the right CardinalityThomas Kytehttp://asktom.oracle.com/