当前位置: 首页 > Oracle, oracle 10g, oracle 11g > 正文

oracle OUTLN用户及使用OUTLINE固定SQL执行计划

今天在写巡检报告时,发现同事写的巡检脚本里把OUTLN用户当成普通用户来分析了。

00005

OUTLN用户是ORACLE自带的用户,默认该用户下的表就是在SYSTEM表空间,这个用户存放ORACLE的SQL执行计划,如果要固定SQL的执行计划,就需要用到这个用户,默认这个用户是锁定的。

SQL> select USERNAME,ACCOUNT_STATUS from dba_users where username='OUTLN';

USERNAME                       ACCOUNT_STATUS
------------------------------ --------------------------------
OUTLN                          EXPIRED & LOCKED

在没有固定SQL执行计划时,OUTLN用户下面的表里是没有数据的。下面演示下怎么固定SQL的执行计划。

  1. 创建测试表,并建立索引
SQL> create table t_test as select * from dba_tables;

表已创建。
SQL> create index i_test_owner on t_test(owner);

索引已创建。
  1. 分别通过索引和全表扫描访问测试表

索引:

SQL> set autotrace on
SQL> select table_name,TABLESPACE_NAME,STATUS from t_test where owner='STREAM';

TABLE_NAME           TABLESPACE_NAME               STATUS
------------------------------ ------------------------------               --------
T_IMAGES            USERS                     VALID
ALERT_DBDREAM_2        USERS                    VALID
TEST              USERS                    VALID
SPERRORLOG           USERS                    VALID
TEST_1             USERS                    VALID

执行计划

----------------------------------------------------------
Plan hash value: 2051741444

------------------------------------------------------------------------------------------------------
| Id  | Operation            | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------
|  0 | SELECT STATEMENT        |       |  5    |  285 |  2   (0)| 00:00:01     |
|   1 |  TABLE ACCESS BY INDEX ROWID   | T_TEST      |  5    | 285   |  2   (0)| 00:00:01     |
|*  2 |   INDEX RANGE SCAN       | I_TEST_OWNER |  5   |    |  1   (0)| 00:00:01     |
------------------------------------------------------------------------------------------------------

全表扫描:

SQL> select /*+full(t_test)*/ table_name,TABLESPACE_NAME,STATUS from t_test where owner='STREAM';

TABLE_NAME                     TABLESPACE_NAME                STATUS
------------------------------ ------------------------------ --------
T_IMAGES                       USERS                          VALID
ALERT_DBDREAM_2                USERS                          VALID
TEST                           USERS                          VALID
SPERRORLOG                     USERS                          VALID
TEST_1                         USERS                          VALID

执行计划

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

Plan hash value: 2796558804

----------------------------------------------------------------------------
| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |     5 |   285 |    20   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T_TEST |     5 |   285 |    20   (0)| 00:00:01 |
----------------------------------------------------------------------------
  1. 分别创建走索引和全表扫描的两条SQL的OUTLINE
SQL> create or replace outline ol_test_ind on select table_name,TABLESPACE_NAME,STATUS from t_test where owner='STREAM';

大纲已创建。
SQL> create or replace outline ol_test_full on select /*+full(test)*/ table_name,TABLESPACE_NAME,STATUS from t_test where owner='STREAM';

大纲已创建。

 

  1. 查询OUTLINE
SQL> select NAME,OWNER,TIMESTAMP,SQL_TEXT from dba_outlines;

NAME         OWNER   TIMESTAMP      SQL_TEXT
------------ ------- -------------- --------------------------------------------------
OL_TEST_IND  STREAM  29-3月 -13     select table_name,TABLESPACE_NAME,STATUS from t_te
st where owner='STREAM'
OL_TEST_FULL STREAM  29-3月 -13     select /*+full(test)*/ table_name,TABLESPACE_NAME,
STATUS from t_test where owner='STREAM'

 

  1. 使用OUTLINE

要使用固定好的执行计划,需要设置USE_STORED_OUTLINES参数值为TRUE。

SQL> alter session set USE_STORED_OUTLINES=TRUE;

会话已更改。
SQL> select table_name,TABLESPACE_NAME,STATUS from t_test where owner='STREAM';

TABLE_NAME                     TABLESPACE_NAME                STATUS
------------------------------ ------------------------------ --------
T_IMAGES                       USERS                          VALID
ALERT_DBDREAM_2                USERS                          VALID
TEST                           USERS                          VALID
SPERRORLOG                     USERS                          VALID
TEST_1                         USERS                          VALID

 

执行计划

----------------------------------------------------------
Plan hash value: 2051741444
--------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              |    56 |  3192 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T_TEST       |    56 |  3192 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | I_TEST_OWNER |    23 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OWNER"='STREAM')
Note
-----
- outline "OL_TEST_IND" used for this statement

 

可以看到已经使用OUTLINE,SQL执行计划成功被固定,也可以使用DBMS_OUTLN包来固定SQL的执行计划。

下面是DBMS_OUTLN包的描述:

SQL> DESC DBMS_OUTLN

PROCEDURE CLEAR_USED
参数名称                       类型                    输入/输出默认值?
------------------------------ ----------------------- ------ --------
NAME                           VARCHAR2                IN
PROCEDURE CREATE_OUTLINE
参数名称                       类型                    输入/输出默认值?
------------------------------ ----------------------- ------ --------
HASH_VALUE                     NUMBER                  IN
CHILD_NUMBER                   NUMBER                  IN
CATEGORY                       VARCHAR2                IN     DEFAULT
PROCEDURE DROP_BY_CAT
参数名称                       类型                    输入/输出默认值?
------------------------------ ----------------------- ------ --------
CAT                            VARCHAR2                IN
PROCEDURE DROP_COLLISION
FUNCTION DROP_COLLISION_EXPACT RETURNS VARCHAR2
PROCEDURE DROP_EXTRAS
FUNCTION DROP_EXTRAS_EXPACT RETURNS VARCHAR2
PROCEDURE DROP_UNREFD_HINTS
FUNCTION DROP_UNREFD_HINTS_EXPACT RETURNS VARCHAR2
PROCEDURE DROP_UNUSED
PROCEDURE EXACT_TEXT_SIGNATURES
PROCEDURE REFRESH_OUTLINE_CACHE
FUNCTION REFRESH_OUTLINE_CACHE_EXPACT RETURNS VARCHAR2
PROCEDURE UPDATE_BY_CAT
参数名称                       类型                    输入/输出默认值?
------------------------------ ----------------------- ------ --------
OLDCAT                         VARCHAR2                IN     DEFAULT
NEWCAT                         VARCHAR2                IN     DEFAULT
PROCEDURE UPDATE_SIGNATURES

 

下面演示使用DBMS_OUTLN包来固定SQL执行计划。首先,先跑一条SQL语句。

SQL> SELECT TABLE_NAME FROM T_TEST WHERE OWNER='STREAM';

TABLE_NAME
------------------------------
T_IMAGES
ALERT_DBDREAM_2
TEST
SPERRORLOG
TEST_1

 

然后,从V$SQL视图中找到这条SQL的HASH_VALUE和CHILD_NUMBER的值。

SQL> SELECT HASH_VALUE,CHILD_NUMBER FROM V$SQL WHERE SQL_TEXT LIKE 'SELECT TABLE_NAME FROM%';

HASH_VALUE CHILD_NUMBER
---------- ------------
3308915684            0

 

接下来就可以使用DBMS_OUTLN包来固定SQL的执行计划了。

SQL> EXEC DBMS_OUTLN.CREATE_OUTLINE(3308915684,0,'IND');

PL/SQL 过程已成功完成。

 

这种方式ORACLE会自动生成OUTLINE的名字。

SQL> select NAME,CATEGORY,SQL_TEXT from dba_outlines;

NAME                           CATEGORY   SQL_TEXT
------------------------------ ---------- --------------------------------------------------
OL_TEST_FULL                   DEFAULT    select table_name,TABLESPACE_NAME,STATUS from t_te
st where owner='STREAM'
SYS_OUTLINE_13032916582825201  IND        SELECT TABLE_NAME FROM T_TEST WHERE OWNER='STREAM'
OL_TEST_IND                    DEFAULT    select /*+full(test)*/ table_name,TABLESPACE_NAME,
STATUS from t_test where owner='STREAM'

 

设置USE_STORED_OUTLINES参数是这个OUTLINE生效,注意这种方式USE_STORED_OUTLINES需要指定OUTLINE的CATEGORY名字。

SQL> ALTER SESSION SET USE_STORED_OUTLINES=IND;

会话已更改。

 

再次执行SQL就会使用到CATEGORY名字为IND的OUTLINE。

SQL> SELECT TABLE_NAME FROM T_TEST WHERE OWNER='STREAM';

TABLE_NAME
------------------------------
T_IMAGES
ALERT_DBDREAM_2
TEST
SPERRORLOG
TEST_1

 

执行计划

----------------------------------------------------------
Plan hash value: 2051741444
--------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              |    56 |  1904 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T_TEST       |    56 |  1904 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | I_TEST_OWNER |    23 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OWNER"='STREAM')
Note
-----
- outline "SYS_OUTLINE_13032916582825201" used for this statement

 

本文固定链接: https://www.dbdream.com.cn/2013/03/oracle-outln%e7%94%a8%e6%88%b7%e5%8f%8a%e4%bd%bf%e7%94%a8outline%e5%9b%ba%e5%ae%9asql%e6%89%a7%e8%a1%8c%e8%ae%a1%e5%88%92/ | 信春哥,系统稳,闭眼上线不回滚!

该日志由 dbdream 于2013年03月29日发表在 Oracle, oracle 10g, oracle 11g 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: oracle OUTLN用户及使用OUTLINE固定SQL执行计划 | 信春哥,系统稳,闭眼上线不回滚!
关键字: , , ,

oracle OUTLN用户及使用OUTLINE固定SQL执行计划:等您坐沙发呢!

发表评论

快捷键:Ctrl+Enter