12c Adaptive Query Optimization – Dynamic Statistics – Examples

Dynamic sampling is used to compensate for missing or insufficient statistics, that would otherwise lead to a bad plan. In earlier versions, dynamic sampling used to kick in for tables that had missing statistics or stale statistics. Dynamic sampling has been enhanced in 12c and is now called dynamic statistics (And most of the functionality, including the new level 11 has been back ported to 11.2.0.4). The optimizer bases its decision to use dynamic statistics, on the complexity of the predicates used, existing base statistics, total execution time expected,Statistics feedback, Sql plan directives etc. The optimizer automatically decides whether dynamic statistics are useful, and what level to use.

Automatic dynamic statistics are enabled when optimizer_dynamic_statistics=2 (Default) or 11.

I have outlined some nuances of Dynamic Statistics in this previous article.

In this article i will show you examples of Dynamic Statistics kicking in for the following situations.

Missing statistics
Stale statistics
Parallel query
Complex where clause
Group by clause

In this Blog post I am not addressing the scenario where dynamic statistics is used , when Sql plan directives are present. I will address that in a future post regarding sql plan directives.

Heads up, this will be a long blog post.

Missing Statistics

When a new table is created, and statistics was not gathered on the table, then oracle will perform dynamic sampling during the optimization of the query, so it can choose a good execution plan.

In the example below, I am creating a new table with data in it, Creating an index on it, and then deleting the statistics on the table.

create table t1
as
select
         *
from
         customers
;

create index t1_idx1 on t1 (cust_state_province)
;

exec dbms_stats.delete_table_stats(upper('SH'),upper('T1'));
commit;

select /*+ gather_plan_statistics */ count(*) from t1 where cust_state_province  = 'CA'

Then I execute a query against the table.

SQL_ID  3azum47vccux0, child number 0                                                                                                                                                                   
-------------------------------------   
select /*+ gather_plan_statistics */ count(*) from t1 where                                                                                                                                             
cust_state_province  = 'CA'                                                                                                                                                                             
                                                                                                                                                                                                        
Plan hash value: 3695297570                                                                                                                                                                             
                                                                                                                                                                                                        
--------------------------------------------------------------------------------------------------------------------------------                                                                        
| Id  | Operation         | Name    | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | Reads  |                                                                        
--------------------------------------------------------------------------------------------------------------------------------                                                                        
|   0 | SELECT STATEMENT  |         |      1 |        |       |    12 (100)|          |      1 |00:00:00.01 |       9 |      2 |                                                                        
|   1 |  SORT AGGREGATE   |         |      1 |      1 |    22 |            |          |      1 |00:00:00.01 |       9 |      2 |                                                                        
|*  2 |   INDEX RANGE SCAN| T1_IDX1 |      1 |   4054 | 89188 |    12   (0)| 00:00:01 |   3341 |00:00:00.01 |       9 |      2 |                                                                        
--------------------------------------------------------------------------------------------------------------------------------                                                                        
                                                                                                                                                                                                        
Query Block Name / Object Alias (identified by operation id):                                                                                                                                           
-------------------------------------------------------------                                                                                                                                           
                                                                                                                                                                                                        
   1 - SEL$1                                                                                                                                                                                            
   2 - SEL$1 / T1@SEL$1                                                                                                                                                                                 
                                                                                                                                                                                                        
Predicate Information (identified by operation id):                                                                                                                                                     
---------------------------------------------------                                                                                                                                                     
                                                                                                                                                                                                        
   2 - access("CUST_STATE_PROVINCE"='CA')                                                                                                                                                               
                                                                                                                                                                                                        
Column Projection Information (identified by operation id):                                                                                                                                             
-----------------------------------------------------------                                                                                                                                             
                                                                                                                                                                                                        
   1 - (#keys=0) COUNT(*)[22]                                                                                                                                                                           
                                                                                                                                                                                                        
Note                                                                                                                                                                                                    
-----                                                                                                                                                                                                   
   - dynamic statistics used: dynamic sampling (level=2)                                                                                                                                                
                                                                                                                                                                                                        

In the Notes section of the execution plan, we can see that dynamic statistics was used with level 2.Since there was no statistics on the table or index, the optimizer performed dynamic sampling, to get estimates. When we review the 10046 trace file and its tkprof output we can see that there are 2 statements executed which has the hint /*+ OPT_DYN_SAMP */ that tells us that dynamic sampling has been performed.

Stale Statistics

In the example below, in order to simulate the behavior of stale statistics, I have done the following

  • Created a table, gathered stats
  • Run a query, and flushed the usage statistics.
  • Inserted more rows into the table.
  • Run a new query, on the table whose statistics is now stale.
  • In order to get the dynamic sampling to kick in, i had to set the optimizer_dynamic_sampling to 11. (Does not kick in when level is 2)

Here is the setup for the example.

create table t1
compress
as
select
         *
from
         customers
;

create index t1_idx1 on t1 (cust_state_province)
;

exec dbms_stats.gather_table_stats(upper('SH'),upper('T1'));
commit;

select /*+ gather_plan_statistics */ count(*) from t1 where cust_state_province  = 'CA'
;

connect sh/sh@10.1.1.202:1521/rkpdb1

insert into t1 select * from t1;
commit;

connect system/manager@10.1.1.202:1521/rkpdb1
exec DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;

connect sh/sh@10.1.1.202:1521/rkpdb1
alter session set optimizer_dynamic_sampling=11
;
@traceon
select /*+ gather_plan_statistics q2 */ count(*) from t1 where cust_state_province  = 'CA'
;


Here is the execution plan for the statement

PLAN_TABLE_OUTPUT                                                                                                                                                                                       
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  1gwst4v211h86, child number 0                                                                                                                                                                   
-------------------------------------                                                                                                                                                                   
select /*+ gather_plan_statistics q2 */ count(*) from t1 where                                                                                                                                          
cust_state_province  = 'CA'                                                                                                                                                                             
                                                                                                                                                                                                        
Plan hash value: 3695297570                                                                                                                                                                             
                                                                                                                                                                                                        
-----------------------------------------------------------------------------------------------------------------------                                                                                 
| Id  | Operation         | Name    | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |                                                                                 
-----------------------------------------------------------------------------------------------------------------------                                                                                 
|   0 | SELECT STATEMENT  |         |      1 |        |       |    21 (100)|          |      1 |00:00:00.01 |      20 |                                                                                 
|   1 |  SORT AGGREGATE   |         |      1 |      1 |    11 |            |          |      1 |00:00:00.01 |      20 |                                                                                 
|*  2 |   INDEX RANGE SCAN| T1_IDX1 |      1 |   6591 | 72501 |    21   (0)| 00:00:01 |   6682 |00:00:00.01 |      20 |                                                                                 
-----------------------------------------------------------------------------------------------------------------------                                                                                 
                                                                                                                                                                                                        
Query Block Name / Object Alias (identified by operation id):                                                                                                                                           
-------------------------------------------------------------                                                                                                                                           
                                                                                                                                                                                                        
   1 - SEL$1                                                                                                                                                                                            
   2 - SEL$1 / T1@SEL$1                                                                                                                                                                                 
                                                                                                                                                                                                        
Predicate Information (identified by operation id):                                                                                                                                                     
---------------------------------------------------                                                                                                                                                     
                                                                                                                                                                                                        
   2 - access("CUST_STATE_PROVINCE"='CA')                                                                                                                                                               
                                                                                                                                                                                                        
Column Projection Information (identified by operation id):                                                                                                                                             
-----------------------------------------------------------                                                                                                                                             
                                                                                                                                                                                                        
   1 - (#keys=0) COUNT(*)[22]                                                                                                                                                                           
                                                                                                                                                                                                        
Note                                                                                                                                                                                                    
-----                                                                                                                                                                                                   
   - dynamic statistics used: dynamic sampling (level=AUTO)      

Now you can see in the note section that dynamic sampling with level AUTO, has been utilized for this query. If you examine the 10046  trace file you will see that there are 2 queries that are executed with the DS_SVC hint in it.

Parallel Query

The following parallel query selects from the tables in the SSB  (Star Schema Benchmark) schema. The execution plan is rather large, so I am not including it below. I am only including the Notes section.

 

SQL_ID  6af5d5js0m4wg, child number 0                                                                                                                                                                   
-------------------------------------                                                                                                                                                                   
SELECT /*+ gather_plan_statistics parallel(4) */                                                                                                                                                        
d_month,s_region,c_region,sum(lo_quantity) FROM                                                                                                                                                         
ssb.lineorder,ssb.date_dim,ssb.customer,ssb.supplier,ssb.part  where                                                                                                                                    
lo_orderdate = d_datekey and    lo_custkey   = c_custkey and                                                                                                                                            
lo_suppkey   = s_suppkey and    lo_partkey   = p_partkey and    d_year                                                                                                                                  
     = 1997 and    p_mfgr       = 'MFGR#1' and    p_category   =                                                                                                                                        
'MFGR#11' and    p_brand1     = 'MFGR#1110' and    s_nation     =                                                                                                                                       
'UNITED STATES' and    c_nation     = 'CHINA' group by                                                                                                                                                  
d_month,s_region,c_region                                                                                                                                                                               
                                                                                                                                                                                                        
Plan hash value: 1014051437                                                                                                                                                                             
                                                                                                                                                                                                        
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---                                                                                                                                                                                                     

| Id  | Operation                          | Name      | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |    TQ  |IN-OUT| PQ Distrib | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem |  O/1/M 
  |                                                                                                                                                                                                     

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---                                                                                                                                                                                                     

|   0 | SELECT STATEMENT                   |           |      1 |        |       | 14066 (100)|          |        |      |            |      3 |00:00:24.64 |      56 |      0 |       |       |        
  |                                                                                                                                                                                                     

|   1 |  PX COORDINATOR                    |           |      1 |        |       |            |          |        |      |            |      3 |00:00:24.64 |      56 |      0 | 73728 | 73728 |        
  
...
...
...
Note                                                                                                                                                                                                    

PLAN_TABLE_OUTPUT                                                                                                                                                                                       
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----                                                                                                                                                                                                   
   - dynamic statistics used: dynamic sampling (level=5)                                                                                                                                                
   - Degree of Parallelism is 4 because of hint         

As you can see in the Note section, the query has performed dynamic sampling. If you remove the parallel hint and run the query then dynamic sampling does not occur.
Here I did not have to modify the optimizer_dynamic_sampling from the default, dynamic statistics still kicks in because it is a parallel query.

Complex Where Clause

Below is a sql with conjunctive predicates in the where clause. This causes oracle to collect dynamic statistics for this query.

 

SELECT /*+ gather_plan_statistics */ *  FROM   customers  WHERE                                                                                                                                         
cust_state_province='CA'  AND    country_id=52790                                                                                                                                                       
                                                                                                                                                                                                        
Plan hash value: 2008213504                                                                                                                                                                             
                                                                                                                                                                                                        
-------------------------------------------------------------------------------------------------------------------------                                                                               
| Id  | Operation         | Name      | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |                                                                               
-------------------------------------------------------------------------------------------------------------------------                                                                               
|   0 | SELECT STATEMENT  |           |      1 |        |       |   405 (100)|          |   3341 |00:00:00.01 |    1677 |                                                                               
|*  1 |  TABLE ACCESS FULL| CUSTOMERS |      1 |   3354 |   592K|   405   (1)| 00:00:01 |   3341 |00:00:00.01 |    1677 |                                                                               
-------------------------------------------------------------------------------------------------------------------------                                                                               
                                                                                                                                                                                                        
Query Block Name / Object Alias (identified by operation id):                                                                                                                                           
-------------------------------------------------------------                                                                                                                                           
                                                                                                                                                                                                        
   1 - SEL$1 / CUSTOMERS@SEL$1                                                                                                                                                                          
                                                                                                                                                                                                        
Predicate Information (identified by operation id):                                                                                                                                                     
---------------------------------------------------                                                                                                                                                     
                                                                                                                                                                                                        
   1 - filter(("CUST_STATE_PROVINCE"='CA' AND "COUNTRY_ID"=52790))                                                                                                                                      
                                                                                                                                                                                                        
Column Projection Information (identified by operation id):                                                                                                                                             
-----------------------------------------------------------                                                                                                                                             
                                                                                                                                                                                                        
   1 - "CUSTOMERS"."CUST_ID"[NUMBER,22], "CUSTOMERS"."CUST_FIRST_NAME"[VARCHAR2,20],                                                                                                                    
       "CUSTOMERS"."CUST_LAST_NAME"[VARCHAR2,40], "CUSTOMERS"."CUST_GENDER"[CHARACTER,1],                                                                                                               
       "CUSTOMERS"."CUST_YEAR_OF_BIRTH"[NUMBER,22], "CUSTOMERS"."CUST_MARITAL_STATUS"[VARCHAR2,20],                                                                                                     
       "CUSTOMERS"."CUST_STREET_ADDRESS"[VARCHAR2,40], "CUSTOMERS"."CUST_POSTAL_CODE"[VARCHAR2,10],                                                                                                     
       "CUSTOMERS"."CUST_CITY"[VARCHAR2,30], "CUSTOMERS"."CUST_CITY_ID"[NUMBER,22], "CUST_STATE_PROVINCE"[VARCHAR2,40],                                                                                 
       "CUSTOMERS"."CUST_STATE_PROVINCE_ID"[NUMBER,22], "COUNTRY_ID"[NUMBER,22],                                                                                                                        
       "CUSTOMERS"."CUST_MAIN_PHONE_NUMBER"[VARCHAR2,25], "CUSTOMERS"."CUST_INCOME_LEVEL"[VARCHAR2,30],                                                                                                 
       "CUSTOMERS"."CUST_CREDIT_LIMIT"[NUMBER,22], "CUSTOMERS"."CUST_EMAIL"[VARCHAR2,30],                                                                                                               
       "CUSTOMERS"."CUST_TOTAL"[VARCHAR2,14], "CUSTOMERS"."CUST_TOTAL_ID"[NUMBER,22],                                                                                                                   
       "CUSTOMERS"."CUST_SRC_ID"[NUMBER,22], "CUSTOMERS"."CUST_EFF_FROM"[DATE,7], "CUSTOMERS"."CUST_EFF_TO"[DATE,7],                                                                                    
       "CUSTOMERS"."CUST_VALID"[VARCHAR2,1]                                                                                                                                                             
                                                                                                                                                                                                        
Note                                                                                                                                                                                                    
-----                                                                                                                                                                                                   
   - dynamic statistics used: dynamic sampling (level=AUTO)                                                              

Here we can see that oracle performed dynamic sampling with level Auto.
I had to set optimizer_dynamic_sampling=11 for this query to perform dynamic sampling.

Group By Clause

The statement below performs dynamic sampling because the groupby clause causes a cardinality misestimate.

 

SQL_ID  8at4un9zmq38c, child number 0                                                                                                                                                                   
-------------------------------------                                                                                                                                                                   
SELECT /*+ gather_plan_statistics */ count(*)  FROM   sh.customers                                                                                                                                      
group by COUNTRY_ID,CUST_STATE_PROVINCE                                                                                                                                                                 
                                                                                                                                                                                                        
Plan hash value: 1577413243                                                                                                                                                                             
                                                                                                                                                                                                        
-----------------------------------------------------------------------------------------------------------------------------------------------------                                                   
| Id  | Operation          | Name      | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem |  O/1/M   |                                                   
-----------------------------------------------------------------------------------------------------------------------------------------------------                                                   
|   0 | SELECT STATEMENT   |           |      1 |        |       |   407 (100)|          |    145 |00:00:00.01 |    1457 |       |       |          |                                                   
|   1 |  HASH GROUP BY     |           |      1 |    145 |  2320 |   407   (1)| 00:00:01 |    145 |00:00:00.01 |    1457 |  1016K|  1016K|     1/0/0|                                                   
|   2 |   TABLE ACCESS FULL| CUSTOMERS |      1 |  55500 |   867K|   405   (1)| 00:00:01 |  55500 |00:00:00.01 |    1457 |       |       |          |                                                   
-----------------------------------------------------------------------------------------------------------------------------------------------------                                                   
                                                                                                                                                                                                        
Query Block Name / Object Alias (identified by operation id):                                                                                                                                           
-------------------------------------------------------------                                                                                                                                           
                                                                                                                                                                                                        
   1 - SEL$1                                                                                                                                                                                            
   2 - SEL$1 / CUSTOMERS@SEL$1                                                                                                                                                                          
                                                                                                                                                                                                        
Column Projection Information (identified by operation id):                                                                                                                                             
-----------------------------------------------------------                                                                                                                                             
                                                                                                                                                                                                        
   1 - "COUNTRY_ID"[NUMBER,22], "CUST_STATE_PROVINCE"[VARCHAR2,40], COUNT(*)[22]                                                                                                                        
   2 - (rowset=256) "CUST_STATE_PROVINCE"[VARCHAR2,40], "COUNTRY_ID"[NUMBER,22]                                                                                                                         
                                                                                                                                                                                                        
Note                                                                                                                                                                                                    
-----                                                                                                                                                                                                   
   - dynamic statistics used: dynamic sampling (level=AUTO)           

Here you can see that dynamic sampling was used with level Auto.
Once you execute this query, if you check the sql plan directives, you will see sql plan directives on this table with Reason of GROUP BY MISSESTIMATE.
I had to set optimizer_dynamic_sampling=11 to get dynamic statistics to kick in.

DIR_ID                                   OWNER OBJECT_NAME               COL_NAME             OBJECT_TYPE               TYPE                    STATE      INST          REASON
---------------------------------------- ----- ------------------------- -------------------- ------------------------- ----------------------- ---------- ------------- ------------------------------------
DC                          LU                         
--------------------------- ---------------------------
13371066972565290282                     SH    CUSTOMERS                 COUNTRY_ID           COLUMN                    DYNAMIC_SAMPLING        USABLE     NEW           GROUP BY CARDINALITY MISESTIMATE     
20-SEP-16 06:39:58                                     

13371066972565290282                     SH    CUSTOMERS                 CUST_STATE_PROVINCE  COLUMN                    DYNAMIC_SAMPLING        USABLE     NEW           GROUP BY CARDINALITY MISESTIMATE     
20-SEP-16 06:39:58                                     

13371066972565290282                     SH    CUSTOMERS                                      TABLE                     DYNAMIC_SAMPLING        USABLE     NEW           GROUP BY CARDINALITY MISESTIMATE     
20-SEP-16 06:39:58 

The examples above can give you some working knowledge of when Dynamic Statistics comes into play with Oracle 12c.

Leave a Reply

Your email address will not be published. Required fields are marked *