By Franck Pachot

.
12c is coming with more dynamic sampling, now called dynamic statistics and using the new Adaptive Dynamic Sampling algorithm. The goal is to have better estimations and better estimations gives better execution plans. However, this new approach will increase parse time because dynamic sampling kicks in more often, reads more blocs, and run more queries.

It’s probably not a problem for applications that are well designed, using bind variables to avoid to many parses, having good statistics (histograms where it makes sense, extended statistics for correlated columns). The SQL Plan Directives are there to trigger dynamic sampling only where misestimates have been observed. An OLTP application should not parse often, and should not have huge misestimates. A reporting use-case can spend more time on parsing and the few seconds spend to do dynamic sampling will probably benefit to the execution time.

In addition to that, in order to lower the dynamic sampling overhead, Oracle 12c Adaptive Dynamic Sampling run its queries with the /*+ result_cache(snapshot=3600) */ hint. The result is cached in the result cache and is not invalidated by dependencies. So even when the underlying table is updated, the dynamic sampling result is still valid in cache for 3600 seconds. This is why doing more dynamic sampling is not a big overhead according that:

  • your result cache is sized accordingly. The default (0.25% of MEMORY_TARGET or 0.5% of SGA_TARGET or 1% of SHARED_POOL_SIZE) is probably too low to fit all the dynamic sampling result for frequently parsed statements.
  • your result cache is enabled, meaning that you are in Enterprise Edition

So the question of the day is that I want to know if the RESULT_CACHE hint is just ignored in Standard Edition, or if there is a mechanism that allows it from Adaptive Dynamic Sampling.

If you have a bad application (not using bind variables, parse at each execution) and you are in Standard Edition, then there is a risk that the current parse contention you suffer from (CPU and latches) will be more problematic (more CPU and I/O). Let’s try the following:

declare
 c sys_refcursor;
begin
 for i in 1..100
 loop
  open c for 'select count(*) COUNT'||i||' from DEMO_TABLE where a+b=c+d';
  dbms_sql.return_result(c);
  null;
 end loop;
end;
/

which run 100 times the same statement not using bind variables. So I’m parsing it each time, but it’s reading the same table with same predicate, so the result of dynamic sampling should not change a lot.

I’ll run it in Standard and Enterprise editions, with no dynamic sampling, and with the new AUTO level.

Enterprise Edition with Adaptive Dynamic Sampling

Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production

SQL> show parameter optimizer_dynamic_sampling
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_dynamic_sampling           integer     11

I’m in Enterprise Edition and with the new AUTO dynamic sampling level (11). Here are a few statistics from v$mystat:

NAME                                                                        VALUE
------------------------------------------------------------ --------------------
parse count (hard)                                                            204
parse count (total)                                                           654
parse time cpu                                                                 59
parse time elapsed                                                             79
recursive calls                                                             4,460
session logical reads                                                     312,198

when I check result cache statistics, I can see that ‘Find Count’ reaches the number of executions:

        ID NAME                           VALUE
---------- ------------------------------ --------
         1 Block Size (Bytes)             1024
         2 Block Count Maximum            5120
         3 Block Count Current            32
         4 Result Size Maximum (Blocks)   256
         5 Create Count Success           17
         6 Create Count Failure           0
         7 Find Count                     104
         8 Invalidation Count             0
         9 Delete Count Invalid           0
        10 Delete Count Valid             0
        11 Hash Chain Length              1
        12 Find Copy Count                104
        13 Latch (Share)                  0

Enterprise Edition without Dynamic Sampling

Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production

SQL> show parameter optimizer_dynamic_sampling
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_dynamic_sampling           integer     0

I’m in Enterprise Edition but disabled the dynamic sampling.

NAME                                                                        VALUE
------------------------------------------------------------ --------------------
parse count (hard)                                                            196
parse count (total)                                                           342
parse time cpu                                                                 29
parse time elapsed                                                             38
recursive calls                                                             3,527
session logical reads                                                     310,785

Here the parse time is smaller because we have less recursive calls. But the difference is not that big. Which means that the dynamic sampling was not a big overhead, thanks to result cache.

Standard Edition without Dynamic Sampling

Connected to:
Oracle Database 12c Release 12.1.0.1.0 - 64bit Production

SQL> show parameter optimizer_dynamic_sampling
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_dynamic_sampling           integer     0

I’m now connected to a Standard Edition with the dynamic sampling disabled:

NAME                                                                        VALUE
------------------------------------------------------------ --------------------
parse count (hard)                                                            167
parse count (total)                                                           271
parse time cpu                                                                 26
parse time elapsed                                                             22
recursive calls                                                             2,131
session logical reads                                                     309,449

This is very similar to the previous one. When dynamic sampling is not enabled, then the parsing time is similar in SE and in EE.

Standard Edition with Adaptive Dynamic Sampling

Connected to:
Oracle Database 12c Release 12.1.0.1.0 - 64bit Production

SQL> show parameter optimizer_dynamic_sampling
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_dynamic_sampling           integer     11

And finally here is the level=AUTO dynamic sampling in Standard Edition:

NAME                                                                        VALUE
------------------------------------------------------------ --------------------
parse count (hard)                                                            204
parse count (total)                                                           649
parse time cpu                                                                690
parse time elapsed                                                            879
recursive calls                                                             4,256
session logical reads                                                   1,019,986

This is where we have a problem. Now wit Adaptive Dynamic Sampling, we are doing the same number of recursive calls as in EE but the result cache is not there to optimize them. My parse time is 10x higher. The number of blocks read is huge. there is no result cache here. And I’ve been running the queries from the same session where an internal cache is supposed to help.

Conclusion

The result cache – which is very important to ensure that the new 12c adaptive dynamic sampling is not a huge overhead at parsing – is not available in Standard Edition. Which means that if you already have parsing issues, you should solve them before gping to 12c or maybe you will have to disable the adaptive dynamic sampling.