Skip to Main Content
  • Questions
  • Optimizer Dynamic Sampling at OPTIMIZER_DYAMIC_SAMPLING level 2

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Navinth.

Asked: February 15, 2017 - 8:11 am UTC

Last updated: March 25, 2017 - 3:49 am UTC

Version: 12.1.0.2

Viewed 1000+ times

You Asked

At my Oracle 12.1.0.2 Oracle Standard Edition database, at OPTIMIZER_DYNAMIC_SAMPLING = 2 which is the default, I see Dynamic Sampling is happening for some of the SQLs for which all tables already have already gathered table statistics. Due to this, big performance drop in some SQL statements compared to previous version Oracle 12.1.0.1. I find this only in upgraded environments (from Oracle 12.1.0.1 to Oracle 12.1.0.2), but not in fresh Oracle 12.1.0.2.

According to the Oracle 12c documentation, at OPTIMIZER_DYNAMIC_SAMPLING = 2 (which is the default value), dynamic statistics is done only if at least one of the tables in the SQL query has no table statistics. But here I can see dynamic sampling is done by optimizer in Oracle 12.1.0.2 version for some of the SQLs (with large tables most of the time). /* DS_SVC */ can be seen in trace files.

Can this be a bug in optimizer logic or am I missing something?

and Connor said...

This is also in the documentation

"There are cases where the optimizer will automatically decide to use 11, for example:
- The query will run in parallel.
- The query was executed before and its history is available (from the cursor cache, Automatic Workload Repository, or the SQL Management Base)."

Could these be applicable to you ?

Rating

  (7 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Navinth Bakmeedeniya, February 16, 2017 - 6:15 am UTC

Thanks for the response.

1. The query will run in parallel. - No. We are not using parallel execution.
2. The query was executed before and its history is available (from the cursor cache, Automatic Workload Repository, or the SQL Management Base) - Well. Dynamic Sampling was detected at the very first execution as well.

So both the above scenarios are not applicable in our case.
Connor McDonald
February 17, 2017 - 12:57 am UTC

1) Run the query with the GATHER_PLAN_STATISTICS hint and send us the output of

select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));

2)

Generate a 10053 trace, and email it to asktom_us@oracle.com, and we'll see what we can find out.

SQL Plan directives

Rajeshwaran, Jeyabal, February 17, 2017 - 10:47 am UTC

Can those dynamic sampling be possible because of SQL Plan directives?

once they migrated to new environment (12.1.0.2) the new optimizer is aware of column level statistics (since they gathered the basic statistics at table level or Online stats gathering during direct path loads) but not the column group statistics, and this column group statistics got detected automatically at execution by SQL Plan directives.

could that be possible here?
http://www.oracle.com/technetwork/issue-archive/2015/15-jul/o45asktom-2606896.html
Connor McDonald
February 18, 2017 - 4:35 am UTC

Certainly a possibility

Navinth Bakmeedeniya, February 20, 2017 - 5:36 am UTC

Hi Connor,

I checked the User_stat_extensions dictionary view for my table & I can see a row for my column combination. I guess this means we already have extended statistics for this table. Since they are present, wonder why the optimizer still doing dynamic sampling.

Also as I mentioned, the issue is not present in Oracle 12.1.0.1 databases which were upgraded from Oracle 11g.
Issue only present in Oracle 12.1.0.2. & thus a specific issue in 12.1.0.2 optimizer?

I'm in the process of generating reports you requested & will send them soon.

Thanks & Best Regards,
Navinth
Connor McDonald
February 21, 2017 - 1:53 am UTC

That is not a livesql script - that's just a link to your session. You need to save the livesql worksheet as a script, which gives a link to allow sharing it with us

A reader, February 21, 2017 - 2:29 am UTC

Hi Connor,
Sorry. I didn't get you correctly.. 'not a livesql' - hope this is related to dbms_xplan output? or you mentioned about the extended statistics (group stats)?

Thanks & Best Regards,
Navinth
Connor McDonald
February 22, 2017 - 1:33 am UTC

Sorry for the confusion, that was a comment to a different question review that I erroneously put in here

Navinth Bakmeedeniya, February 21, 2017 - 5:58 am UTC

Hi Connor,

Now I sent the trace files you requested to asktom_us@oracle.com.

Thanks & Best Regards,
Navinth

Navinth Bakmeedeniya, March 04, 2017 - 2:36 pm UTC

Hi Connor,

Do you have any update on this issue?
Any findings based on the traces I sent?

Thanks & Best Regards,
Navinth
Connor McDonald
March 23, 2017 - 5:05 am UTC

Hi. It it due to sql plan directives. If we get a bad estimate (versus the actuals) we might "make a note" that if we see that query again, we should do some dynamic sampling via a "sql plan directive", eg


SQL> create table t
  2  as
  3  select *
  4  from dba_objects a
  5  union all
  6  select *
  7  from dba_objects a
  8  where owner = 'SYS'
  9  ;

Table created.

SQL>
SQL> create index t_ix on t ( owner );

Index created.

SQL>
SQL> exec dbms_stats.gather_table_stats('','T',method_opt=>'for all columns size 1');

PL/SQL procedure successfully completed.

SQL>
SQL> commit;

Commit complete.

--
-- so our database currently has 279 directives already there
--
SQL>
SQL> select count(*) from DBA_SQL_PLAN_DIRECTIVES;

  COUNT(*)
----------
       279

1 row selected.

--
-- now I run my query
--
SQL> select /*+ gather_plan_statistics */ count(created) from t where owner = 'SYS' and object_type in ('SYNONYM','JAVA CLASS');

COUNT(CREATED)
--------------
         55480

1 row selected.

SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------
SQL_ID  2up5bxj23rp92, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ count(created) from t where owner
= 'SYS' and object_type in ('SYNONYM','JAVA CLASS')

Plan hash value: 1874539213

-------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |      |      1 |        |      1 |00:00:00.03 |    2174 |
|   1 |  SORT AGGREGATE                      |      |      1 |      1 |      1 |00:00:00.03 |    2174 |
|*  2 |   TABLE ACCESS BY INDEX ROWID BATCHED| T    |      1 |    152 |  55480 |00:00:00.03 |    2174 |
|*  3 |    INDEX RANGE SCAN                  | T_IX |      1 |   3568 |  84814 |00:00:00.02 |     179 |
-------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(("OBJECT_TYPE"='JAVA CLASS' OR "OBJECT_TYPE"='SYNONYM'))
   3 - access("OWNER"='SYS')


22 rows selected.

--
-- You can see above, the actuals differed hugely from the estimate.  We notice this
-- and mark the statement as perhaps needing more optimization work.
--
-- You can see this on V$SQL
--


SQL>
SQL> select sql_text, is_reoptimizable
  2  from v$sql
  3  where sql_text like 'select /*+ gather_plan_statistics */ count(created)%';

SQL_TEXT                                                         I
---------------------------------------------------------------- -
select /*+ gather_plan_statistics */ count(created) from t where Y
 owner = 'SYS' and object_type in ('SYNONYM','JAVA CLASS')


1 row selected.

--
-- Normally, after 15mins, we'd flush what we need in terms of getting
-- better optimization, but we can flush it manually
--

SQL>
SQL> exec   dbms_spd.flush_sql_plan_directive;

PL/SQL procedure successfully completed.

--
-- and we get some new directives.
--

SQL>
SQL> select count(*) from DBA_SQL_PLAN_DIRECTIVES;

  COUNT(*)
----------
       281

1 row selected.

--
-- Now when I run my query again, notice the new notes at the bottom
--

SQL>
SQL> select /*+ gather_plan_statistics */ count(created) from t where owner = 'SYS' and object_type in ('SYNONYM','JAVA CLASS');

COUNT(CREATED)
--------------
         55480

1 row selected.

SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------
SQL_ID  2up5bxj23rp92, child number 1
-------------------------------------
select /*+ gather_plan_statistics */ count(created) from t where owner
= 'SYS' and object_type in ('SYNONYM','JAVA CLASS')

Plan hash value: 2966233522

-------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |      1 |        |      1 |00:00:00.01 |    2270 |
|   1 |  SORT AGGREGATE    |      |      1 |      1 |      1 |00:00:00.01 |    2270 |
|*  2 |   TABLE ACCESS FULL| T    |      1 |  55480 |  55480 |00:00:00.01 |    2270 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(("OWNER"='SYS' AND INTERNAL_FUNCTION("OBJECT_TYPE")))

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)
   - statistics feedback used for this statement
   - 1 Sql Plan Directive used for this statement


26 rows selected.

SQL>
SQL>
SQL>


The sql plan directive said - "we dont have good enough stats to satisfy this query, so next time, do some dynamic sampling"


Navinth Bakmeedeniya, March 23, 2017 - 8:20 am UTC

But this happens when we have already gathered table statistics for all the tables in the query. I think If these statistics were good enough to estimate the cardinalities correctly, there should be no need of this Dynamic Sampling at this point. Thus I suspect this as a bug in your table statistics gathering logic.

When Dynamic Sampling is done for somewhat large tables, it takes very long time compared to the actual execution time even with a wrong cardinality estimate resulting significant performance problems.
Connor McDonald
March 25, 2017 - 3:49 am UTC

Review my example again - I had "good" stats as well. But sometimes the stats stored are *not* enough, ie, we can't have stats on *every* possible combination of predicates and values.

For example, there is no set of stats that can give a good estimate for:

where COL1 in ('A','B','C')
and   COL2 > 10
and   COL3 != COL4
and   COL5 is not null



More to Explore

Performance

Get all the information about database performance in the Database Performance guide.