1.SQL计划指令介绍
我们知道统计反馈(SFB)收集的SQL运行时的统计信息会保存在相应的共享游标中,但却不能够持久化,
当数据库重启或者被优化的SQL文从内存中Age-out后,保存的信息就会丢失。下一次执行时还要重新进行一遍自动重新优化。
为了缓解这个问题Oracle 12c推出了SQL指令计划(SQL Plan Directives 以后简称SPD)功能,保存为了以后生成最优
执行计划的一些指令和附加信息到字典表中,达到持久化的目的。
虽然到目前为止,只有一种SQL计划指令就是动态采样指令(DYNAMIC_SAMPLING),用于指示优化器使用动态统计信息,
但相信以后该功能会进一步得到强化。
SQL计划指令对于优化器来说就像"额外的笔记",提醒优化器现在正在使用一个不是最优的执行计划,典型的就是由于错误
的基数估计,错误的基数估计通常是由于缺少统计信息,足够的数据,复杂的谓词,复杂的操作造成的。
另外,SQL计划指令(SQL Plan Directives)和sql profile有所不同,spd是基于查询表达式,而不是SQL语句,
所以同一个SQL计划指令(SQL Plan Directives),可以被优化器应用多个SQL文中。
由12c自动重新优化(Automatic Reoptimization)相关功能,生成相关SQL计划指令(SPD)后,会暂时把信息保存在内存的共享池中。
Oracle的后台进程会每隔15分钟把SQL计划指令(SPD)相关信息从共享池中保存到SYSAUX表空间内相关的字典表中。
当然,你也可以通过手动调用DBMSSPD.FLUSHSQLPLANDIRECTIVE函数,实时地把相关信息从共享池中保存到相关的字典表中。
可以通过DBA_SQL_PLAN_DIRECTIVES and DBA_SQL_PLAN_DIR_OBJECTS视图查看SQL计划指令的详细信息。
--手动刷新数据到数据字典
EXEC DBMS_SPD.FLUSH_SQL_PLAN_DIRECTIVE;
当然这个保留时间也不是无限制的,如果在53周时间内该SQL计划指令没有被使用过,那么就会被自动删除掉。
--查看SQL计划指令(SPD)的保存期间
SQL> SELECT DBMS_SPD.GET_PREFS('SPD_RETENTION_WEEKS') FROM dual; DBMS_SPD.GET_PREFS('SPD_RETENTION_WEEKS') ----------------------------------------- 53
-- 修改保存期间
SQL> exec DBMS_SPD.SET_PREFS('SPD_RETENTION_WEEKS',10)
-- 查看修改后的保存期间
SQL> SELECT DBMS_SPD.GET_PREFS('SPD_RETENTION_WEEKS') FROM dual; DBMS_SPD.GET_PREFS('SPD_RETENTION_WEEKS') ----------------------------------------- 10
2.测试部分
2.1清空共享池
SQL> alter session set container=zhixin; Session altered. SQL> alter system flush shared_pool; System altered.
2.2测试数据准备
CREATE TABLE tab1 ( id NUMBER, gender VARCHAR2(1), has_y_chromosome VARCHAR2(1), CONSTRAINT tab1_pk PRIMARY KEY (id), CONSTRAINT tab1_gender_chk CHECK (gender IN ('M', 'F')), CONSTRAINT tab1_has_y_chromosome_chk CHECK (has_y_chromosome IN ('Y', 'N')) );
INSERT /*+ APPEND */ INTO tab1 SELECT level, 'M', 'Y' FROM dual CONNECT BY level <= 10; COMMIT;
INSERT /*+ APPEND */ INTO tab1 SELECT 10+level, 'F', 'N' FROM dual CONNECT BY level <= 90; COMMIT;
CREATE INDEX tab1_gender_idx ON tab1(gender); CREATE INDEX tab1_has_y_chromosome_idx ON tab1(has_y_chromosome); EXEC DBMS_STATS.gather_table_stats(USER, 'TAB1');
2.3查看直方图
#尽管数据有倾斜,但是使用默认设置收集数据的时候没有产生直方图。
SQL> COLUMN column_name FORMAT A20 SQL> SELECT column_id, 2 column_name, histogram FROM user_tab_columns 5 WHERE table_name = 'TAB1' 6 ORDER BY column_id; COLUMN_ID COLUMN_NAME HISTOGRAM ---------- -------------------- ------------------------------ 1 ID NONE 2 GENDER NONE 3 HAS_Y_CHROMOSOME NONE
2.4查看执行计划
常识我们都知道男性是有一个Y染色体的,而女的是没有的。但是优化器是不知道这个关系的,
所以它没有直方图去表示数据的倾斜。所以对于谓词的选择性不会做出最好的估计。假设数据是
均匀的,那么应该一半是男性,而且有Y染色体。
SELECT /*+ GATHER_PLAN_STATISTICS */ 2 * FROM tab1 4 WHERE gender = 'M' 5 AND has_y_chromosome = 'Y'; ID GE HA ---------- -- -- 1 M Y 2 M Y 3 M Y 4 M Y 5 M Y 6 M Y 7 M Y 8 M Y 9 M Y 10 M Y 10 rows selected.
SQL> SET LINESIZE 200 PAGESIZE 100 SQL> SELECT * FROM TABLE(DBMS_XPLAN.display_cursor(format => 'allstats last')); PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------------------------------- SQL_ID 5t8y8p5mpb99j, child number 0 ------------------------------------- SELECT /*+ GATHER_PLAN_STATISTICS */ * FROM tab1 WHERE gender = 'M' AND has_y_chromosome = 'Y' Plan hash value: 1552452781 ----------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ----------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 10 |00:00:00.01 | 4 | |* 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TAB1 | 1 | 25 | 10 |00:00:00.01 | 4 | |* 2 | INDEX RANGE SCAN | TAB1_GENDER_IDX | 1 | 50 | 10 |00:00:00.01 | 2 | ----------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("HAS_Y_CHROMOSOME"='Y') 2 - access("GENDER"='M') 21 rows selected.
如预期一样,优化器确实得到了错误的基数估计( E-Rows 的值)。这个是个典型的案例直方图,扩展的统计信息
会帮助优化器更准确的估计基数。
2.5查看sql是否被重新优化
查看V$SQL视图中IS_REOPTIMIZABLE列表示优化器是否注意到了错误的基数估计。
COLUMN sql_text FORMAT A40 COLUMN is_reoptimizable FORMAT A16 SELECT sql_text, is_reoptimizable FROM v$sql WHERE sql_id = '5t8y8p5mpb99j'; SQL_TEXT IS_REOPTIMIZABLE ---------------------------------------- ---------------- SELECT /*+ GATHER_PLAN_STATISTICS */ Y * FROM tab1 WHERE gender = 'M' AN D has_y_chromosome = 'Y' SQL>
Y表示,该SQL被标记为重新优化,也很有肯能是已经创建了SQL计划指令。
3.查看SQL计划指令(SPD)
现在优化计划指令还在SGA中,所以我们还是看不见的。
SET LINESIZE 200
COLUMN dir_id FORMAT A20 COLUMN owner FORMAT A10 COLUMN object_name FORMAT A10 COLUMN col_name FORMAT A10 SELECT TO_CHAR(d.directive_id) dir_id, o.owner, o.object_name, o.subobject_name col_name, o.object_type, d.type, d.state, d.reason FROM dba_sql_plan_directives d, dba_sql_plan_dir_objects o WHERE d.directive_id=o.directive_id AND o.owner = 'LEI' ORDER BY 1,2,3,4,5; no rows selected SQL>
可以等数据库自动刷新,也可以手动刷新数据到数据字典中。.
SQL> EXEC DBMS_SPD.flush_sql_plan_directive; PL/SQL procedure successfully completed.
SELECT TO_CHAR(d.directive_id) dir_id, o.owner, o.object_name, o.subobject_name col_name, o.object_type, d.type, d.state, d.reason FROM dba_sql_plan_directives d, dba_sql_plan_dir_objects o WHERE d.directive_id=o.directive_id AND o.owner = 'LEI' ORDER BY 1,2,3,4,5; DIR_ID OWNER OBJECT_NAM COL_NAME OBJECT TYPE STATE REASON -------------------- ---------- ---------- ---------- ------ ---------------- ---------- ------------------------------------ 11749925840852248025 LEI TAB1 GENDER COLUMN DYNAMIC_SAMPLING USABLE SINGLE TABLE CARDINALITY MISESTIMATE 11749925840852248025 LEI TAB1 TABLE DYNAMIC_SAMPLING USABLE SINGLE TABLE CARDINALITY MISESTIMATE SQL>
4.查看SQL计划指令使用情况
再次执行这个已经产生过sql计划指令的sql,注意后面输出部分的信息。
SQL> SELECT /*+ GATHER_PLAN_STATISTICS */ * FROM tab1 WHERE gender = 'M' AND has_y_chromosome = 'Y'; SQL> SET LINESIZE 200 PAGESIZE 100 SQL> SELECT * FROM TABLE(DBMS_XPLAN.display_cursor(format => 'allstats last')); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- SQL_ID 5t8y8p5mpb99j, child number 1 ------------------------------------- SELECT /*+ GATHER_PLAN_STATISTICS */ * FROM tab1 WHERE gender = 'M' AND has_y_chromosome = 'Y' Plan hash value: 1552452781 ----------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | ----------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 10 |00:00:00.01 | 4 | |* 1 | TABLE ACCESS BY INDEX ROWID BATCHED| TAB1 | 1 | 10 | 10 |00:00:00.01 | 4 | |* 2 | INDEX RANGE SCAN | TAB1_GENDER_IDX | 1 | 10 | 10 |00:00:00.01 | 2 | ----------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("HAS_Y_CHROMOSOME"='Y') 2 - access("GENDER"='M') Note ----- - dynamic statistics used: dynamic sampling (level=2) - statistics feedback used for this statement - 1 Sql Plan Directive used for this statement 27 rows selected. SQL>
note部分提示很清楚,一个sql计划指令被使用了。
5.SQL计划指令和统计信息
SQL计划指令就是一个通常表明"丢失的信息"。这些信息可能会在未来变成有用的,如果重新收集表tab1的统计信息,
可以看到直方图了。
SQL> EXEC DBMS_STATS.gather_table_stats(USER, 'TAB1'); PL/SQL procedure successfully completed. SQL> SELECT column_id, column_name, histogram FROM user_tab_columns WHERE table_name = 'TAB1' ORDER BY column_id; COLUMN_ID COLUMN_NAME HISTOGRAM ---------- -------------------- --------------- 1 ID NONE 2 GENDER FREQUENCY 3 HAS_Y_CHROMOSOME FREQUENCY SQL>
#如果有扩展的统计信息,可以通过下面查询看到
SELECT extension_name,extension FROM user_stat_extensions;
一旦所需的直方图或扩展的统计信息是存在的,或者另一个SQL计划指令被创建,SQL计划指示可能变成SUPERSEDED和no longer used状态。
SELECT state, COUNT(*) FROM dba_sql_plan_directives GROUP BY state 4 ORDER BY state; STATE COUNT(*) -------------------- ---------- SUPERSEDED 129 USABLE 157 SQL>
官方文档:http://docs.oracle.com/database/121/TGSQL/tgsql_statscon.htm#TGSQL347
版权声明:本文为博主原创文章,未经博主允许不得转载。
SQL plan directives
- 上一篇:ceph OSD的添加,删除
- 下一篇:12C新特性--Adaptive Plans