Oracle Scratchpad

May 1, 2007

Optimizer Environment

Filed under: Troubleshooting — Jonathan Lewis @ 8:28 pm BST May 1,2007

Last update: July 2023

From time to time you may notice that a single SQL statement has several different child cursors visible in v$sql. One reason for this happening is that different sessions may be running with different optimizer environments; for example your setting for the parameter optimizer_mode might be all_rows while mine is first_rows_1. If your optimizer environment is different from my optimizer environment then we cannot share cursors and we may end up using different execution plans for the same text.

Oracle 10g allows us to see the optimizer environment at the system, session, and individual SQL level, through v$sys_optimizer_env, v$ses_optimizer_env, and v$sql_optimizer_env respectively. This can be very helpful when tracking down the source of unexpected behaviour. For example:

rem
rem     Script:         optimizer_env.sql
rem     Author:         Jonathan Lewis
rem     Dated:          May 2007
rem

select
        first_load_time, child_number, last_load_time,
        plan_hash_value, loads, executions
from
        v$sql
where
        sql_id = 'g4pkmrqrgxg3b'
;    

FIRST_LOAD_TIME     CHILD_NUMBER LAST_LOAD_TIME      PLAN_HASH_VALUE LOADS EXECUTIONS
------------------- ------------ ------------------- --------------- ----- ----------
2007-04-27/08:21:19            0 2007-04-27/08:21:19      2598313856     1          2
2007-04-27/08:21:19            1 2007-04-27/08:22:44       647803999     1          1   

When we notice that we have two child cursors for the same statement generated within a few minutes of each other (notice the last_load_time) we can run, from 10g and above, the following query query to see if it gives us any clues:

break on child_number skip 1    

select
        child_number, name, value
from    v$sql_optimizer_env
where
        sql_id = 'g4pkmrqrgxg3b'
order by
        child_number,
        name
;    

CHILD_NUMBER NAME                                     VALUE
------------ ---------------------------------------- -------------------------
           0 _db_file_optimizer_read_count            16
             active_instance_count                    1
             bitmap_merge_area_size                   1048576
             cpu_count                                2
             cursor_sharing                           exact
             hash_area_size                           131072
             optimizer_dynamic_sampling               2
             optimizer_features_enable                10.2.0.3
             optimizer_index_caching                  0
             optimizer_index_cost_adj                 100
             optimizer_mode                           first_rows_1
             optimizer_secure_view_merging            true
             parallel_ddl_mode                        enabled
             parallel_dml_mode                        disabled
             parallel_execution_enabled               true
             parallel_query_mode                      enabled
             parallel_threads_per_cpu                 2
             pga_aggregate_target                     204800 KB
             query_rewrite_enabled                    true
             query_rewrite_integrity                  enforced
             skip_unusable_indexes                    true
             sort_area_retained_size                  0
             sort_area_size                           65536
             sqlstat_enabled                          true
             star_transformation_enabled              false
             statistics_level                         typical
             workarea_size_policy                     auto  

           1 _db_file_optimizer_read_count            16
             _hash_join_enabled                       false
             active_instance_count                    1
             bitmap_merge_area_size                   1048576
             cpu_count                                2
             cursor_sharing                           exact
             hash_area_size                           131072
             optimizer_dynamic_sampling               2
             optimizer_features_enable                10.2.0.3
             optimizer_index_caching                  0
             optimizer_index_cost_adj                 100
             optimizer_mode                           first_rows_1
             optimizer_secure_view_merging            true
             parallel_ddl_mode                        enabled
             parallel_dml_mode                        disabled
             parallel_execution_enabled               true
             parallel_query_mode                      enabled
             parallel_threads_per_cpu                 2
             pga_aggregate_target                     204800 KB
             query_rewrite_enabled                    true
             query_rewrite_integrity                  enforced
             skip_unusable_indexes                    true
             sort_area_retained_size                  0
             sort_area_size                           65536
             sqlstat_enabled                          true
             star_transformation_enabled              false
             statistics_level                         typical
             workarea_size_policy                     auto  

In this case, you can see that one of the cursors was generated by a session that had disabled hash joins. One convenience of this view is that it doesn’t normally show the hidden parameters but (just like v$parameter) if someone has modified a hidden parameter the parameter does show up.

Update (9th July 2015)

In the latest version of Oracle (12.1.0.2) the number of rows visible in v$sql_optimizer_env is up to 60; but the underlying structure (x$kqlfsqce) has 470 parameters listed. Even then this doesn’t tell you everything because if a session has modified its NLS parameters the changes don’t appear in the view, and the NLS parameters could have a significant effect on execution plans.

Update (March 2022)

A quick update for 19.11.0.0 which now has 69 parameter generally visible, but 613 in total.

Update (July 2023)

Information about the optimizer environment has been part of the AWR for many years in the view dba_hist_optimizer_env, but this has only ever reported a single hashed result of the optimizer environment values. From 21c a new view dba_hist_optimzier_env_details expands the optimizer_env_hash_value to a list of parameter/value pairs. See MOS Doc id: 2953121.1

In passing the 23c version of v$sys_optimizer_env reports 78 distinct values while the underlying x$qkscesys reports 658 (which you can also find in the 10053 trace file.)

15 Comments »

  1. Hi Jonathan,

    After an upgrade of a database from 8i to 9i, fresh statistics have been gathered but the optimizer_fearures_enabled was set to 8.1.7. Now, I want to set this parameter to 9.2.0, do I need to re-gather the statistics ?

    Regards

    Comment by viveshar — August 21, 2007 @ 5:14 pm BST Aug 21,2007 | Reply

  2. Viveshar,

    There is no special need to collect stats again – the collection in 9i is not significantly different from the collection in 8i. However you will find that the 9i optimizer has a number of options that are not available in 8i so some executon plans may change quite dramatically.

    Two particular changes to watch out for are subquery unnesting and bitmap conversions.

    Comment by Jonathan Lewis — August 21, 2007 @ 7:03 pm BST Aug 21,2007 | Reply

  3. Hi Jonathan,

    I noticed a change in the OPTIMIZER_ENV_HASH_VALUE for a SQL_ID in the DBA_HIST_SQLSTAT. The PLAN_HASH_VALUE remained the same for that SQL ID.

    AWR has got a view called DBA_HIST_OPTIMIZER_ENV
    which contains a column in raw named OPTIMIZER_ENV.

    Can I use this column to determine what has changed for the optimizer ?

    Regards

    Comment by Hans — September 24, 2010 @ 12:39 pm BST Sep 24,2010 | Reply

    • Hans,

      Possibly – I remember Julian Dyke talking about this column as it appears in v$sql and saying something about how he’d worked out how to unravel it. You may find something about it on his website.

      If there’s nothing on the website, you could dump a 10053 trace, and cross check v$sql_optimizer_env for a child cursor with the raw column in v$sql and the trace output and see how the raw output varies as you modify different optimizer parameters. Personally I wouldn’t bother because it’s the type of thing that’s fairly likely to change on every point release.

      Comment by Jonathan Lewis — September 25, 2010 @ 8:53 am BST Sep 25,2010 | Reply

  4. Hi Jonathan,

    if a session changes PGA workarea policy to MANUAL setting and other PGA parameters this generates a child cursor with a different execution plan. Can this child cursor be shared by another session that uses a different optimizer environment ? If yes how Oracle chooses which child cursor should be used ?

    Regards,

    Atta

    Comment by attagianno — November 3, 2011 @ 12:35 am GMT Nov 3,2011 | Reply

    • Atta,

      No – the optimizer environment is a critical part of generating an execution plan.
      If you check v$sql you will find that there are two columns assocated with the optimizer environment: optimizer_env (which is a raw listing of the optimizer environment in which the statement was optimized) and optimizer_env_hash_value – which I assume is the thing that a session uses as a quick check to determine that a child cursor is not appropriate for it to use.

      Comment by Jonathan Lewis — November 13, 2011 @ 3:41 pm GMT Nov 13,2011 | Reply

  5. […] I decided to take a look at recent developments in the “fix control” list, and the “optimizer environment” parameters. Here’s a breakdown of the number of entries in recent versions of […]

    Pingback by Upgrades « Oracle Scratchpad — September 22, 2012 @ 11:02 am BST Sep 22,2012 | Reply

  6. Hi Jonathan,
    I have a performance issue on client side; The query causing the performance issue have all the time the same execution plan but two optimizer_env_hash_value. I have found this on DBA_HIST_SQLSTAT ; for one of these optimizer_env_hash_value the query takes an important time to be executed. The query is executed (with the bad optimizer_env_hash_value) many times between Day J 11H30 and DAY J+1 00h:30. I can not found this sql_id into v$sql_optimizer_env. Does this mean that a Oracle parameter has been modified ?

    Thanks,
    Cherif.

    Comment by bijga — March 2, 2013 @ 10:28 pm GMT Mar 2,2013 | Reply

    • bijga,
      The basic answer to your question is that if the optimizer_env_hash_value has changed then one of the optimizer parameters has changed. v$sql_optimizer_env, however, only shows a fraction of the total number of parameters.

      How are you able to find the two different execution plans without finding the v$sql_optimizer_env ?

      It is possible to get the same plan_hash_value (which means the same “shape” of execution plan with the same object names) and get different execution paths. When working out the plan_hash_value, Oracle doesn’t consider the predicate sections, or the object_id; there are several consequences that might apply.

      If identically named objects exist in different schemas, you could end up with two plans that look the same and have the same plan_hash_value but reference different objects and happen to perform very differently.

      If sessions have different optimizer environments (e.g. manual vs. automatic pga) then they could get exactly the same plans from exactly the same objects with exactly the same query for exactly the same data – but still do different amounts of work, such as sorting to disc instead of memory.

      If the sessions have different NLS settings if may be that the plans look alike, but the predicate show one plan doing a very efficient access on character predicate while the other needs to do a much less efficient filter over a much larger range scan.

      It’s even possible that a change in the optimizer environment could be “harmless”, but the person with the different environment just happens to be the person that uses a bind variable that does a lot more work – perhaps a check v$sql for the two child cursors would show that one averages a lot more rows returned than the other.

      Apart from looking for v$sql_optimizer_env, you could look at v$sql_shared_cursor for clues why new cursors appeared.

      *** I pressed “reply” and then realised that perhaps you can see v$sql_optimizer_env and they look the same. If you have access as SYS, you can query the x$ that sits under v$sql_optimizer_env. and that’s x$kqlfsqce, which you can access through columns KQLFSQCE_SQLID and KQLFSQCE_CHNO. If you can’t access the x$ then, with the right version of Oracle, you might be able to enable trace event 10132 for just that SQL statement and dump the full optimizer environment to disc every time it is optimised – I’ll have to check the method before publishing it, though.

      *** Follow-up: the following seems to do almost what I would want (in 11.1.0.7, at least):

      alter system set events '10132 [SQL:cvmkv0hyc7xhp]'
      

      This dumps a trace file showing the statement, plan, outline, predicates, bind_variables and complete optimizer environment and a few other bits and pieces every time the given SQL_ID is optimized. The trouble is it does seem to do the same for any recursive SQL related to populating the dictionary cache at the same time.

      Comment by Jonathan Lewis — March 3, 2013 @ 3:35 pm GMT Mar 3,2013 | Reply

  7. Hello Jonathan,
    Does collecting stats or doing DDL change the optimizer environment? We have an application that does both too often and I think this is causing a lot of re-parsing. Incredibly this thing drops and creates tables as part of the code. I need additional info to say how bad this is.

    Comment by Matt B — March 26, 2019 @ 11:44 pm GMT Mar 26,2019 | Reply

    • Matt B,

      Neither of those will change the optimizer environment, but dropping a table and recreating it will invalidate the cursors on any queries referencing the table. Similarly, any other structural DDL on a table (e.g. adding, rebuilding an index) will invalidate cursors on the object.

      Gathering stats on an object will EVENTUALLY result in cursor invalidation if parameters are left at default (specifically no_invalidate => auto), but this will only happen as some point in the next few hours. The net effect will depend somewhat on how you gather stats, what sort of SQL you execute, and (inevitably) which version of Oracle you’re using.

      The thing about invalidations, however, is that Oracle you tend to see Oracle “re-loading” child cursors rather than generating new ones, so a query against v$sql for invalidattions and loads will give you some idea of the impact of the drop/create or gather stats coding. e.g.

      
      SQL> select invalidations , loads from v$sql where sql_id = '1jcg4h88r6y98';
      
      INVALIDATIONS      LOADS
      ------------- ----------
                  2          3
      
      

      Comment by Jonathan Lewis — March 27, 2019 @ 11:41 am GMT Mar 27,2019 | Reply

  8. Hello, Jonathan,
    Do you know how to modifiy the default value for parallel_query_mode in v$sys_optimizer_env ?
    i have tried with alter system set parallel_query_mode = ‘disabled’;
    or
    ALTER System disable PARALLEL QUERY;
    it does not work.
    thank you
    regards
    Dominique

    Comment by Dominique — March 19, 2020 @ 2:50 pm GMT Mar 19,2020 | Reply

  9. […] Optimizer Environment (May 2007): seeing details of the optimizer parameter settings in v$sql_optimzer_env etc. (Updated to 23c). […]

    Pingback by Troubleshooting catalogue | Oracle Scratchpad — July 28, 2023 @ 1:26 pm BST Jul 28,2023 | Reply

  10. […] Optimizer Environment (May 2007): seeing details of the optimizer parameter settings in v$sql_optimzer_env etc. (Updated to 23c). […]

    Pingback by Optimizer catalogue | Oracle Scratchpad — July 28, 2023 @ 1:26 pm BST Jul 28,2023 | Reply


RSS feed for comments on this post. TrackBack URI

Comments and related questions are welcome.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Website Powered by WordPress.com.