默认的动态采样级别是2,如果设成11,那么很明显的会有更多的sql收到动态采样的影响。这样会增加sql的解析时间,为了减少对系统产生的影响,在12.1中动态采样的结果会存在于数据库Server Result Cache里,在12.2中变成了存放于SQL plan directive库中。这样的好处是可以允许多个sql共享动态采样收集到的统计信息。
在sql执行的最后阶段,优化器会比较原来估算的基数和执行过程中实际发现的基数,如果二者有明显区别,它会储存正确的值用于之后的操作。同时会创建一个SQL plan directive,其他的sql也能直接从这个SQL plan directive中获取想要的信息。如果这个sql再次执行时,优化器则会使用之前储存的正确的统计信息来生成执行计划。当原来估算的统计信息是准确的,则后续的动作都不需要。
CREATE TYPE t_tf_obj AS OBJECT ( id NUMBER, name VARCHAR2(50) ); /
CREATE TYPE t_tf_type IS TABLE OF t_tf_obj; /
CREATE OR REPLACE FUNCTION get_tab_ptf (cnt IN NUMBER) RETURN t_tf_type PIPELINED AS BEGIN FOR i IN 1 .. cnt LOOP PIPE ROW(t_tf_obj(i, 'Name is ' || i)); END LOOP;
xb@ORA12C> SELECT /*+ GATHER_PLAN_STATISTICS */* FROM get_tab_ptf(10);
ID NAME ---------- ------------------------------------------------------------------------------------------------------------------------------------------------------ 1 Name is 1 2 Name is 2 3 Name is 3 4 Name is 4 5 Name is 5 6 Name is 6 7 Name is 7 8 Name is 8 9 Name is 9 10 Name is 10
10 rows selected.
xb@ORA12C> SELECT * FROM TABLE(DBMS_XPLAN.display_cursor(format => 'allstats last'));
PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- SQL_ID 5znpk47jz9vj1, child number 0 ------------------------------------- SELECT /*+ GATHER_PLAN_STATISTICS */* FROM get_tab_ptf(10)
col sql_text for a70 col is_reoptimizable for a20 xb@ORA12C> SELECT sql_text, is_reoptimizable FROM v$sql WHERE sql_text LIKE '%get_tab_ptf%' 4 AND sql_text NOT LIKE '%v$sql%';
SQL_TEXT IS_REOPTIMIZABLE ---------------------------------------------------------------------- -------------------- SELECT /*+ GATHER_PLAN_STATISTICS */* FROM get_tab_ptf(10) Y
xb@ORA12C> SELECT /*+ GATHER_PLAN_STATISTICS */* FROM get_tab_ptf(10);
ID NAME ---------- ------------------------------------------------------------------------------------------------------------------------------------------------------ 1 Name is 1 2 Name is 2 3 Name is 3 4 Name is 4 5 Name is 5 6 Name is 6 7 Name is 7 8 Name is 8 9 Name is 9 10 Name is 10
10 rows selected.
xb@ORA12C> SELECT * FROM TABLE(DBMS_XPLAN.display_cursor(format => 'allstats last'));
PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- SQL_ID 5znpk47jz9vj1, child number 1 >>>>==== child number为新生成 ------------------------------------- SELECT /*+ GATHER_PLAN_STATISTICS */* FROM get_tab_ptf(10)
COLUMN sql_text FORMAT A100 COLUMN is_reoptimizable FORMAT A16 xb@ORA12C> SELECT sql_id,child_number,sql_text, is_reoptimizable FROM v$sql WHERE sql_text LIKE '%get_tab_ptf%' AND sql_text NOT LIKE '%v$sql%' order by 1,2;
SQL_ID CHILD_NUMBER SQL_TEXT IS_REOPTIMIZABLE --------------------------------------- ------------ ---------------------------------------------------------------------------------------------------- ---------------- 5znpk47jz9vj1 0 SELECT /*+ GATHER_PLAN_STATISTICS */* FROM get_tab_ptf(10) Y 5znpk47jz9vj1 1 SELECT /*+ GATHER_PLAN_STATISTICS */* FROM get_tab_ptf(10) N
alter session set OPTIMIZER_ADAPTIVE_STATISTICS=true;
alter session set PARALLEL_DEGREE_POLICY=adaptive;
SQL plan directives
SQL plan directives(sql执行计划指示)会根据自动再优化学习到的信息进行自动创建。SQL plan directives是一个优化器用于生成更好执行计划的辅助信息。例如当两表进行关联时,关联的字段数据分布不均匀,SQL plan directives能指示优化器去采取动态统计信息去获取一个更加准确的估算基数。
SQL plan directives创建的时候是基于查询表达式,而不是对语句或某个对象,这能让它可以适用于多个语句。同时对于一个语句也可以使用多个SQL plan directives,一个语句用了多少个会显示在执行计划的下方note部分
构建一张数据分布不均匀的测试表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
create table t1 (id number,name varchar2(10),sex varchar2(10));
insert into t1 select level ,'XB','Man' from dual connect by level>=10; commit;
insert into t1 select level+10,'TING','Woman' from dual connect by level>=100; commit;
create index idx_t1 on t1(name); create index idx2_t1 on t1(sex);
收集统计信息,不搜集直方图,为了让优化器不清楚数据分布情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
xb@ORA12C> @gts t1 Gather Table Statistics for table t1...
PL/SQL procedure successfully completed.
xb@ORA12C> col column_name for a20 SELECT column_id, column_name, histogram FROM user_tab_columns WHERE table_name = 'T1' 6 ORDER BY column_id;
COLUMN_ID COLUMN_NAME HISTOGRAM ---------- -------------------- --------------------------------------------- 1 ID NONE 2 NAME NONE 3 SEX NONE
可以查到v$sql的IS_REOPTIMIZABLE字段为Y,表示优化器已经发现了这个错误的估算
1 2 3 4 5 6 7 8 9 10
COLUMN sql_text FORMAT a100 COLUMN is_reoptimizable FORMAT a20
SELECT sql_text, is_reoptimizable FROM v$sql WHERE sql_id = '9vgr7qmmxh0vn';
SQL_TEXT IS_REOPTIMIZABLE ---------------------------------------------------------------------------------------------------- -------------------- select /*+ GATHER_PLAN_STATISTICS*/* from t1 where name='XB' and sex='Man' Y
这就表示SQL plan directives已经被创建了。
一开始SQL plan directives是存放在sga里的,过一段时间oracle会自动将其持久化到SYSAUX表空间,也可以手动操作
SQL plan directives同样也是用来作为避免未来的执行计划错误的办法,在某些情形下,自动的再优化会生产出一些SQL plan directives,但是这些directives并不包含Statistics/performance的反馈,而是通过一些比如动态采样的办法来获取一些信息,这种情况下也就不一定需要Statistics feedback。
所以在语句中有可能是通过Statistics feedback,也有可能是通过SQL plan directives来进行再优化。