暂无图片
分享
HunterHuang
2019-05-23
dba_sql_plan_baselines.reproduced value not update?

 

db version: 12.1.0.2.0

rdbms home: /paic/dev/oracle/rdbms/12c/12.1.0.2.170418

 

we used sql plan management in our production database, recently we found when a plan become unproduced such as index was dropped, the value of dba_sql_plan_baselines.reproduced can't update to 'NO'.

 

I also tested the scenario in testing environment, for one simple sql, I generated a full table scan plan and a index scan plan in sql plan baseline, after that, I dropped the index, so the index scan plan should not be reproduced, but the value of dba_sql_plan_baselines.reproduced still is 'YES', seems it will never be update to 'NO'. so I want to ask why the value will not update while actually the plan is not reproduced? and when will oracle update the value to 'NO', and how?

 

updated my testing scripts in attachment?

 

-----------------------------------------testting scripts---------------------------

--spm parameter
SQL> show parameter sql_plan

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
_sql_plan_directive_mgmt_control     integer     0
optimizer_capture_sql_plan_baselines boolean     FALSE
optimizer_use_sql_plan_baselines     boolean     TRUE
SQL>
SQL>

-----create test table
create table my_objects as select * from dba_objects;

SQL>
SQL> create table my_objects as select * from dba_objects;

Table created.

SQL>

------create index
create index idx1_my_objects on my_objects(object_id);

SQL> create index idx1_my_objects on my_objects(object_id);

Index created.

-----gather table stats
exec dbms_stats.gather_table_stats('DEVMGR','MY_OBJECTS',cascade => true);

SQL>
SQL> exec dbms_stats.gather_table_stats('DEVMGR','MY_OBJECTS',cascade => true);

PL/SQL procedure successfully completed.

SQL>

-----run query sql, we can see with index scan execution plan

select /*SMP_QUESTION*/  object_id from my_objects where object_id=88;

SQL> set autotrace on
SQL> select /*SMP_QUESTION*/  object_id from my_objects where object_id=88;

OBJECT_ID
----------
        88

Execution Plan
----------------------------------------------------------
Plan hash value: 3367122391

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

| Id  | Operation        | Name            | Rows  | Bytes | Cost (%CPU)| Time
   |

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

|   0 | SELECT STATEMENT |                 |     1 |     5 |     1   (0)| 00:00:
01 |

|*  1 |  INDEX RANGE SCAN| IDX1_MY_OBJECTS |     1 |     5 |     1   (0)| 00:00:
01 |

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

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

   1 - access("OBJECT_ID"=88)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          3  consistent gets
          0  physical reads
          0  redo size
        543  bytes sent via SQL*Net to client
        552  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL>

-----load the plan into spm
SQL> set autotrace off
SQL> SELECT SQL_ID,PLAN_HASH_VALUE FROM V$SQL WHERE SQL_TEXT LIKE '%SMP_QUESTION%' and plan_hash_value=3367122391 and sql_text not like '%EXPLAIN PLAN%';

SQL_ID        PLAN_HASH_VALUE
------------- ---------------
4zjugzdm6aus2      3367122391

SQL>

--before load,no baseline
SQL> SELECT sql_handle, plan_name,enabled, accepted ,fixed,reproduced FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE '%SMP_QUESTION%';

no rows selected

SQL>

--load baseline
declare
v_load_plan_number number;
begin
v_load_plan_number:=dbms_spm.LOAD_PLANS_FROM_CURSOR_CACHE(SQL_ID=>'4zjugzdm6aus2',PLAN_HASH_VALUE=>'3367122391');
end;
/

SQL>
SQL> declare
  2  v_load_plan_number number;
  3  begin
  4  v_load_plan_number:=dbms_spm.LOAD_PLANS_FROM_CURSOR_CACHE(SQL_ID=>'4zjugzdm6aus2',PLAN_HASH_VALUE=>'3367122391');
  5  end;
  6  /

PL/SQL procedure successfully completed.

SQL>
SQL>

--after load,plan enabled=YES,accepted=YES,fixed=NO,reproduced=YES
SELECT sql_handle, plan_name,enabled, accepted ,fixed,reproduced FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE '%SMP_QUESTION%';

SQL> set linesize 300
SQL> col sql_handle for a30
SQL> col plan_name for a40
SQL> SELECT sql_handle, plan_name,enabled, accepted ,fixed,reproduced FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE '%SMP_QUESTION%';

SQL_HANDLE                     PLAN_NAME                                ENA ACC FIX REP
------------------------------ ---------------------------------------- --- --- --- ---
SQL_d4456e0393f81c5e           SQL_PLAN_d8jbf0f9zh72yeaf2dc42           YES YES NO  YES

SQL>

--with spm plan SQL_PLAN_d8jbf0f9zh72yeaf2dc42,and it's ACCEPTED,so when run the query sql again, we can see used the spm plan
SQL> set autotrace on
SQL> select /*SMP_QUESTION*/  object_id from my_objects where object_id=88;

OBJECT_ID
----------
        88

Execution Plan
----------------------------------------------------------
Plan hash value: 3367122391

------------------------------------------------------------------------------------
| Id  | Operation        | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |                 |     1 |     5 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IDX1_MY_OBJECTS |     1 |     5 |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------

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

   1 - access("OBJECT_ID"=88)

Note
-----
   - SQL plan baseline "SQL_PLAN_d8jbf0f9zh72yeaf2dc42" used for this statement

Statistics
----------------------------------------------------------
         27  recursive calls
         18  db block gets
         12  consistent gets
          0  physical reads
       5488  redo size
        543  bytes sent via SQL*Net to client
        552  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL>

---then I drop the index
drop index IDX1_MY_OBJECTS;
SQL> set autotrace off
SQL> drop index IDX1_MY_OBJECTS;

Index dropped.

SQL>

--after index dropped, the query go full table scan, and will capture full table scan plan into spm

SQL> set autotrace on
SQL> select /*SMP_QUESTION*/  object_id from my_objects where object_id=88;

OBJECT_ID
----------
        88

Execution Plan
----------------------------------------------------------
Plan hash value: 880823944

--------------------------------------------------------------------------------
| Id  | Operation         | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |            |     1 |     5 |   421   (1)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| MY_OBJECTS |     1 |     5 |   421   (1)| 00:00:01 |
--------------------------------------------------------------------------------

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

   1 - filter("OBJECT_ID"=88)

Statistics
----------------------------------------------------------
        211  recursive calls
         40  db block gets
       1685  consistent gets
          1  physical reads
       8116  redo size
        543  bytes sent via SQL*Net to client
        552  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         18  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL>

---the index has dropped, but when we view DBA_SQL_PLAN_BASELINES, the value of reproduced is still YES, why can't update to 'NO'?

SQL> set autotrace off
SQL> SELECT sql_handle, plan_name,enabled, accepted ,fixed,reproduced FROM DBA_SQL_PLAN_BASELINES WHERE SQL_TEXT LIKE '%SMP_QUESTION%';

SQL_HANDLE                     PLAN_NAME                                ENA ACC FIX REP
------------------------------ ---------------------------------------- --- --- --- ---
SQL_d4456e0393f81c5e           SQL_PLAN_d8jbf0f9zh72y89405218           YES NO  NO  YES
SQL_d4456e0393f81c5e           SQL_PLAN_d8jbf0f9zh72yeaf2dc42           YES YES NO  YES

SQL>

收藏
分享
5条回答
默认
最新
Kamus

在19c中也重现了同样的问题,按照文档的描述确实在drop index之后,这个sql plan baseline应该是被标记为non-reproduced,但是确实reproduced字段一直是显示为YES。

SQL> select origin,version,accepted,reproduced FROM DBA_SQL_PLAN_BASELINES;

ORIGIN			      VERSION			     ACC REP
----------------------------- ------------------------------ --- ---
AUTO-CAPTURE		      19.0.0.0.0		     NO  YES
MANUAL-LOAD-FROM-CURSOR-CACHE 19.0.0.0.0		     YES YES
复制


不确认是不是跟baseline是MANUAL-LOAD-FROM-CURSOR-CACHE进来的有关?

暂无图片 评论
暂无图片 有用 0
打赏 0
HunterHuang

 我们也在跟Oracle确认这个问题,但目前还没有收到准确的结论。我先补充另外三个点:

  1. 我们对删除索引后的sql查询做了10053,可以看到优化器已经判断出了 reproduced='NO' 并且甚至说了 change REPRODUCED status to NO, 但是view里面还是不会刷新。

  2. 我们生产上也有reproduced='NO'并且是MANUAL-LOAD,不知道是怎么产生的

  3. 现在不知道也没有其他办法可以将一条baseline主动地修改为reproduced='NO'


    ---10053截取---

1896 SPM: finding a match for the generated plan, planId = 2302693912

1897 SPM: planId's of plan baseline are: 3941784642

1898 SPM: using qksan to reproduce, cost and select accepted plan, sig = 15295752671080225886

1899 SPM: plan reproducibility round 1 (plan outline + session OFE)

1900 SPM: using qksan to reproduce accepted plan, planId = 3941784642

1901 Registered qb: SEL$1 0x62383c98 (PARSER)

 

 

 

3774 SPM: planId in plan baseline = 3941784642, planId of reproduced plan = 2302693912

3775 ------- START SPM Plan Dump -------

3776 SPM: failed to reproduce the plan using the following info:

3777   parse_schema name        : DEVMGR

3778   plan_baseline signature  : 15295752671080225886

3779   plan_baseline plan_id    : 3941784642

3780   plan_baseline hintset    :

3781     hint num  1 len 27 text: IGNORE_OPTIM_EMBEDDED_HINTS

3782     hint num  2 len 37 text: OPTIMIZER_FEATURES_ENABLE('12.1.0.2')

3783     hint num  3 len 22 text: DB_VERSION('12.1.0.2')

3784     hint num  4 len 42 text: OPT_PARAM('_bloom_filter_enabled' 'false')

3785     hint num  5 len  8 text: ALL_ROWS

3786     hint num  6 len 22 text: OUTLINE_LEAF(@"SEL$1")

3787     hint num  7 len 63 text: INDEX(@"SEL$1" "MY_OBJECTS"@"SEL$1" ("MY_OBJECTS"."OBJECT_ID"))

3788 SPM: generated non-matching plan:

3789 ----- Explain Plan Dump -----

3790 ----- Plan Table -----

 

19542 SPM: change REPRODUCED status to NO, planName = SQL_PLAN_d8jbf0f9zh72yeaf2dc42

19543 SPM: couldn't reproduce any enabled+accepted plan so using the cost-based plan, planId = 2302693912

19544 kkeCostToTime: using io calibrate stats maxpmbps=200(MB/s)

19545  block_size=8192 mb_io_count=1 mb_io_size=8192 (bytes)

19546  tot_io_size=3(MB) time=16(ms)

19547 kkeCostToTime: using io calibrate stats maxpmbps=200(MB/s)

19548  block_size=8192 mb_io_count=1 mb_io_size=8192 (bytes)

19549  tot_io_size=3(MB) time=16(ms)

19550 kkeCostToTime: using io calibrate stats maxpmbps=200(MB/s)

19551  block_size=8192 mb_io_count=1 mb_io_size=8192 (bytes)

19552  tot_io_size=3(MB) time=16(ms)

19553 kkeCostToTime: using io calibrate stats maxpmbps=200(MB/s)

19554  block_size=8192 mb_io_count=1 mb_io_size=8192 (bytes)

19555  tot_io_size=3(MB) time=16(ms)

19556 Starting SQL statement dump

暂无图片 评论
暂无图片 有用 0
打赏 0
Kamus

如果Oracle有回复,那么请回来补充一下。非常感谢。

不过,虽然这个字段在视图中没有更新,但是从功能性上看,却并未有损害,这倒是还能接受的。

10053的显示很正确,因此我暂时倾向于认为这是一个比较低级的bug。


查了DBA_SQL_PLAN_BASELINE的视图定义,在基表中也是没有更新的。

SELECT /*+ dynamic_sampling(3) */
    so.signature,
    st.sql_handle,
    st.sql_text,
    so.name,
    ad.creator,
    DECODE(ad.origin, 1,  'MANUAL-LOAD',
                      2,  'AUTO-CAPTURE',
                      3,  'MANUAL-SQLTUNE',
                      4,  'AUTO-SQLTUNE',
                      5,  'STORED-OUTLINE',
                      6,  'EVOLVE-CREATE-FROM-ADAPTIVE',
                      7,  'MANUAL-LOAD-FROM-STS',
                      8,  'MANUAL-LOAD-FROM-AWR',
                      9,  'MANUAL-LOAD-FROM-CURSOR-CACHE',
                      10, 'EVOLVE-LOAD-FROM-STS',
                      11, 'EVOLVE-LOAD-FROM-AWR',
                      12, 'EVOLVE-LOAD-FROM-CURSOR-CACHE',
                      13, 'ADDM-SQLTUNE',
                      14, 'EVOLVE-AUTO-INDEX-LOAD',
                         'UNKNOWN'),
    ad.parsing_schema_name,
    ad.description,
    ad.version,
    ad.created,
    ad.last_modified,
    so.last_executed,
    ad.last_verified,
    DECODE(BITAND(so.flags, 1),   0, 'NO', 'YES'),
    DECODE(BITAND(so.flags, 2),   0, 'NO', 'YES'),
    DECODE(BITAND(so.flags, 4),   0, 'NO', 'YES'),
    DECODE(BITAND(so.flags, 64),  0, 'YES', 'NO'),
    DECODE(BITAND(so.flags, 8),   0, 'NO', 'YES'),
    DECODE(BITAND(so.flags, 256), 0, 'NO', 'YES'),
    ad.optimizer_cost,
    substrb(ad.module,1,(select ksumodlen from x$modact_length)) module,
    substrb(ad.action,1,(select ksuactlen from x$modact_length)) action,
    ad.executions,
    ad.elapsed_time,
    ad.cpu_time,
    ad.buffer_gets,
    ad.disk_reads,
    ad.direct_writes,
    ad.rows_processed,
    ad.fetches,
    ad.end_of_fetch_count
FROM
    sqlobj$        so,
    sqlobj$auxdata ad,
    sql$text       st
WHERE
    so.signature = st.signature AND
    ad.signature = st.signature AND
    so.signature = ad.signature AND
    so.category = ad.category AND
    so.plan_id = ad.plan_id AND
    so.obj_type = 2 AND
    ad.obj_type = 2
复制


bitand之后的结果确实也都是YES

SQL> select DECODE(BITAND(flags, 64),  0, 'YES', 'NO') from sqlobj$;

DEC
---
YES
YES
复制


暂无图片 评论
暂无图片 有用 0
打赏 0
HunterHuang

 Kamus你好,

回复的有点晚了,这个问题我们提了SR给Oracle,跟了一段时间,得到了一些反馈,但是好像他们也无法完全回答清楚这个问题。

他们回答说之前有人提过这个问题的BUG,但是最后被认定为一个Expected behaviour,他们认为实时更新这个字段的值会有非常大的性能问题,包括dba_sql_plan_baselines.last_executed也不是实时更新。

另外,好像REPRODUCED的值是在需要读取outline,并且outline已经unproduced的时候,会更新这个值为NO,我们生产系统上大部分NO的值也是Origin从stored-outline的。

得到了很多人的反馈,但好像还是无法完整的回答清楚这个问题。


下面是他们的一些主要的回复,请参考。

Hello Hunter -  


Some time back another customer raised this issue whihc my colleague has mentioned also and it was found that it is an expected behavior.

Bug 15984910   : DBA_SQL_PLAN_BASELINE.REPRODUCED FLAG IS NOT CLEARED, WHEN THE PLAN IS NO LONGER  
This was later on deemed as not a bug but an expected behavior.

Here is the note from our sustaining engineering team

@ This is expected behavior.  The REPRODUCED column will only change when the
@ optimizer read the outlines of the plans and tries to reproduce them.  In
@ many cases, however, the optimizer will not read any of the outlines since
@ the default cost-based plan matches one of the accepted plans.  In such
@ cases, the optimizer can declare that it has used the best SQL plan baseline,
@ and there is no need to read any other SQL plan baseline's outlines or to
@ try to reproduce them.

You raised this question how would you identify which plans in baseline are not reproducible if you someone in your development has dropped whole bunch of indexes - there is no easy way to do it.
If the sql runs next time and if optimizer decides to use a plan in baseline by reading the outline like the developer has mentioned in the note above and then finds it is not reproducible it will mark it as reproduced = NO. Otherwise the reproduced column value will not change.


Bottom line - sql plan baselines are used for plan stabilization solution - but if the underlying objects are changed/dropped - the plan in the baseline is not valid any more if the outline is not reproducible.  

Before letting anyone dropping indexes you have to do an impact analysis which sqls and which baselines will affected.
Then you need to drop and recreate baseline if required -  
I am afraid it is a manual process and it will remain like this in foreseeable future.

   


暂无图片 评论
暂无图片 有用 0
打赏 0
HunterHuang
问题已关闭: 问题已经得到解决
暂无图片 评论
暂无图片 有用 0
打赏 0
回答交流
Markdown


请输入正文
提交
相关推荐
请问下,拷贝的备份注册目录不上是什么原因?
回答 1
已采纳
我个人建议如下:1确认/backup目录权限2确认/backup中文件权限3/backup中是备份集还是归档文件?4可以通过catalogbackuppiece和alterdatabaseregist
oracle 12c ADG库注册catalog报错
回答 2
在主库连接到备库(adg):rmancatalogrman/rman@laaRMAN>createcatalog;成功exit主库上:rmantarget/catalogrman/rman@la
DSG占用物理读很高
回答 2
已采纳
dsg不都是原厂服务的吗?直接找原厂哇
Oracle怎么弄模拟数据?
回答 1
可以使用DBeaver的企业版(网上有破解版),自己创建表结构,然后选中刚创建的表单机右键——工具——GenerateMockData,可以自动生成地址、邮件、姓名等数据。
大表建索引
回答 2
已采纳
注意回滚段、临时段、归档日志位置、表所在的表空间的空间,避免空间不足。执行期间不要CTRLC或者关闭窗口在dml语句执行比较少的时段执行
关于oracle删除数据后,表空间使用问题
回答 1
已采纳
按时间做分区表,每次drop2个月之前的分区,保留从上个月1号至今的数据,不过需要注意索引可能需要重建
Oracle的ora-01207能不能重建控制文件修复?
回答 1
可以参考下:https://www.modb.pro/db/133675;
oracle 11g rac 双节点查询sql耗时不同
回答 1
看等待事件是什么,做个ash
19crac 应用datapatch报错
回答 6
步骤是安装安装说明做的,就是最后一步应用datapatchverbose的时候报错了,报错日志如附件
问下,有一个视图使用dblink访问远程数据,目前访问这个视图很不稳定,有时很慢,这个怎么处理?
回答 3
分析步骤:1确认相关SQL的执行计划,表和索引的信息,统计信息等2部署监控测试网络连接和性能情况3查询历史相关SQL的sqlid的执行计划确认执行计划是否变化4查询对端DB性能情况,排除干扰