[20130123]spm与sql profile的主要区别在那里.txt

[20130123]spm与sql profile的主要区别在那里.txt

    SPM是11G的新特性,而10g下sql profile一定程度代替store ountlined来稳定执行计划,oracle为什么11G下还要推出SPM?
两者区别主要在那里呢?

我举一个例子来说明:

1.建立测试环境:

select * from v$version where rownum
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production

create table t1 as select mod(rownum,100) id ,lpad('x',80,'x') name from dual connect by level
insert into t1 values (100,lpad('y',80,'y')) ;
commit ;
create index i_t1_id on t1(id);
exec dbms_stats.gather_table_stats(user,'T1',method_opt=>'for all columns size 1');
create table t2 as select mod(rownum,100) id ,lpad('x',80,'x') name from dual connect by level
insert into t2 values (100,lpad('y',80,'y')) ;
commit ;
create index i_t2_id on t2(id);
exec dbms_stats.gather_table_stats(user,'T2',method_opt=>'for all columns size 1');

--我没有建立直方图!
--t1,t2信息一样,id数值是从0-99均匀分布,而id=100仅仅1个,理论讲上面使用索引效果更加。但是由于索引的聚集因子很大,几乎接
--近记录大小。这样oracle认为数据很离散,执行计划并不会使用索引 [注意:我并没有建立直方图。]

SQL> select clustering_factor  from dba_indexes  where wner=user and index_name in ('I_T1_ID','I_T2_ID');
CLUSTERING_FACTOR
-----------------
            10001
            10001
--看看一下语句的sql语句:
select * from t1 where id=100;
SQL> select * from t1 where id=100;
        ID NAME
---------- --------------------------------------------------
       100 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
           yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy

SQL> @dpc ''
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  c9bya8ajdfsg3, child number 0
-------------------------------------
select * from t1 where id=100
Plan hash value: 3617692013
--------------------------------------------------------
| Id  | Operation         | Name | E-Rows | Cost (%CPU)|
--------------------------------------------------------
|   0 | SELECT STATEMENT  |      |        |    53 (100)|
|*  1 |  TABLE ACCESS FULL| T1   |     99 |    53   (0)|
--------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("ID"=100)
--可以发现oracle认为数据很离散,但是系统并不知道id=100很少[并没有建立直方图],仅仅1条,按照道理使用索引效率很高,而实际
--的执行计划是全表扫描.
2.测试使用sql profile来优化看看:
DECLARE
  ret_val VARCHAR2(4000);
BEGIN
  ret_val := DBMS_SQLTUNE.CREATE_TUNING_TASK(
                sql_id          => 'c9bya8ajdfsg3',
                plan_hash_value => NULL,
                scope       => 'COMPREHENSIVE',
                time_limit  => 1800,
                task_name   => 'test',
                description => 'study');
  Dbms_Sqltune.EXECUTE_TUNING_TASK('test');
END;
select Dbms_Sqltune.REPORT_TUNING_TASK('test', 'TEXT', 'all') report from dual;
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name   : test
Tuning Task Owner  : SCOTT
Tuning Task ID     : 8871
Workload Type      : Single SQL Statement
Execution Count    : 1
Current Execution  : EXEC_9150
Execution Type     : TUNE SQL
Scope              : COMPREHENSIVE
Time Limit(seconds): 1800
Completion Status  : COMPLETED
Started at         : 01/23/2013 09:45:04
Completed at       : 01/23/2013 09:45:04
-------------------------------------------------------------------------------
Schema Name: SCOTT
SQL ID     : c9bya8ajdfsg3
SQL Text   : select * from t1 where id=100
-------------------------------------------------------------------------------
FINDINGS SECTION (1 finding)
-------------------------------------------------------------------------------
1- SQL Profile Finding (see explain plans section below)
--------------------------------------------------------
  为此语句找到了性能更好的执行计划。
  Recommendation (estimated benefit: 98.46%)
  ------------------------------------------
  - 考虑接受推荐的 SQL 概要文件。
    execute dbms_sqltune.accept_sql_profile(task_name => 'test', task_owner
            => 'SCOTT', replace => TRUE);
  Validation results
  ------------------
  已对 SQL profile 进行测试, 方法为执行其计划和原始计划并测量与计划相对应的执行统计信息。如果其中一个计划运行在很短的时间内就完成,
  则另一计划可能只执行了一部分。
                           Original Plan  With SQL Profile  % Improved
                           -------------  ----------------  ----------
  Completion Status:            COMPLETE          COMPLETE
  Elapsed Time(us):                 832                72      91.34 %
  CPU Time(us):                     899               100      88.87 %
  User I/O Time(us):                  0                 0 
  Buffer Gets:                      131                 2      98.47 %
  Physical Read Requests:             0                 0 
  Physical Write Requests:            0                 0 
  Physical Read Bytes:                0                 0 
  Physical Write Bytes:               0                 0 
  Rows Processed:                     1                 1 
  Fetches:                            1                 1 
  Executions:                         1                 1 
  Notes
  -----
  1. original plan 已首先执行以预热缓冲区高速缓存。
  2. original plan 的统计信息是后面的 9 执行的平均值。
  3. SQL profile plan 已首先执行以预热缓冲区高速缓存。
  4. the SQL profile plan 的统计信息是后面的 9 执行的平均值。
-------------------------------------------------------------------------------
EXPLAIN PLANS SECTION
-------------------------------------------------------------------------------
1- Original
-----------
Plan hash value: 3617692013
 
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    99 |  8316 |    53   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |    99 |  8316 |    53   (0)| 00:00:01 |
--------------------------------------------------------------------------
 
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
 
   1 - SEL$1 / T1@SEL$1
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("ID"=100)
 
Column Projection Information (identified by operation id):
-----------------------------------------------------------
 
   1 - "ID"[NUMBER,22], "T1"."NAME"[VARCHAR2,80]
2- Original With Adjusted Cost
------------------------------
Plan hash value: 3617692013
 
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    84 |    53   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |     1 |    84 |    53   (0)| 00:00:01 |
--------------------------------------------------------------------------
 
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
 
   1 - SEL$1 / T1@SEL$1
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("ID"=100)
 
Column Projection Information (identified by operation id):
-----------------------------------------------------------
 
   1 - "ID"[NUMBER,22], "T1"."NAME"[VARCHAR2,80]
3- Using SQL Profile
--------------------
Plan hash value: 1111474805
 
---------------------------------------------------------------------------------------
| Id  | Operation                   | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |         |     1 |    84 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1      |     1 |    84 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | I_T1_ID |     1 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------
 
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
 
   1 - SEL$1 / T1@SEL$1
   2 - SEL$1 / T1@SEL$1
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("ID"=100)
 
Column Projection Information (identified by operation id):
-----------------------------------------------------------
 
   1 - "ID"[NUMBER,22], "T1"."NAME"[VARCHAR2,80]
   2 - "T1".ROWID[ROWID,10], "ID"[NUMBER,22]
-------------------------------------------------------------------------------
--可以发现提示使用索引效果更加,执行如下来稳定计划.
execute dbms_sqltune.accept_sql_profile(task_name => 'test', task_owner=> 'SCOTT', replace => TRUE);
SQL> column signature format 999999999999999999999
SQL> set serveroutput on
SQL> exec print_table('select * from dba_sql_profiles');
NAME                          : SYS_SQLPROF_013c6516f3f90000
CATEGORY                      : DEFAULT
SIGNATURE                     : 10770288213799319469
SQL_TEXT                      : select * from t1 where id=100
CREATED                       : 2013-01-23 09:47:48.000000
LAST_MODIFIED                 : 2013-01-23 09:47:48.000000
DESCRIPTION                   :
TYPE                          : MANUAL
STATUS                        : ENABLED
FORCE_MATCHING                : NO
TASK_ID                       : 8871
TASK_EXEC_NAME                : EXEC_9150
TASK_OBJ_ID                   : 1
TASK_FND_ID                   : 1
TASK_REC_ID                   : 1
-----------------
--查询获得sql profile 的hint。10G使用如下命令。
SELECT attr_val
FROM sys.sqlprof$ p, sys.sqlprof$attr a
WHERE p.sp_name = 'SYS_SQLPROF_013c6516f3f90000'
AND p.signature = a.signature
AND p.category = a.category;
--注意11GR2查询如下:
SELECT EXTRACTVALUE (VALUE (h), '.') AS hint
  FROM SYS.sqlobj$data od, SYS.sqlobj$ so, TABLE (XMLSEQUENCE (EXTRACT (XMLTYPE (od.comp_data), '/outline_data/hint'))) h
 WHERE so.NAME = 'SYS_SQLPROF_013c6516f3f90000'
   AND so.signature = od.signature
   AND so.CATEGORY = od.CATEGORY
   AND so.obj_type = od.obj_type
   AND so.plan_id = od.plan_id;
HINT
-------------------------------------------------------------------------------------
OPT_ESTIMATE(@"SEL$1", TABLE, "T1"@"SEL$1", SCALE_ROWS=0.0100989901)
OPT_ESTIMATE(@"SEL$1", INDEX_SCAN, "T1"@"SEL$1", "I_T1_ID", SCALE_ROWS=0.0100989901)
OPTIMIZER_FEATURES_ENABLE(default)

--可以发现sql profile实际上使用的提示如上。SCALE_ROWS=0.0100989901,表T1的总记录10001条,id不同的键值是0-100,有101个。
--如果执行如下:

select /*+ gather_plan_statistics  
OPT_ESTIMATE(@"SEL$1", TABLE, "T1"@"SEL$1", SCALE_ROWS=0.0100989901)
OPT_ESTIMATE(@"SEL$1", INDEX_SCAN, "T1"@"SEL$1", "I_T1_ID", SCALE_ROWS=0.0100989901) */
* from t1 where id=42;
SQL> @dpc
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  9aytbsm99q6d9, child number 0
-------------------------------------
select /*+ gather_plan_statistics OPT_ESTIMATE(@"SEL$1", TABLE,
"T1"@"SEL$1", SCALE_ROWS=0.0100989901) OPT_ESTIMATE(@"SEL$1",
INDEX_SCAN, "T1"@"SEL$1", "I_T1_ID", SCALE_ROWS=0.0100989901) */ * from
t1 where id=42
Plan hash value: 1111474805
--------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name    | Starts | E-Rows | Cost (%CPU)| A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |         |      1 |        |     2 (100)|    100 |00:00:00.01 |     103 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1      |      1 |      1 |     2   (0)|    100 |00:00:00.01 |     103 |
|*  2 |   INDEX RANGE SCAN          | I_T1_ID |      1 |      1 |     1   (0)|    100 |00:00:00.01 |       3 |
--------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("ID"=42)

--不加提示看看:

select /*+ gather_plan_statistics */ * from t1 where id=42;
SQL> @dpc
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  7utu76jbuat60, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ * from t1 where id=42
Plan hash value: 3617692013
-------------------------------------------------------------------------------------------------
| Id  | Operation         | Name | Starts | E-Rows | Cost (%CPU)| A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |      1 |        |    53 (100)|    100 |00:00:00.01 |     147 |
|*  1 |  TABLE ACCESS FULL| T1   |      1 |     99 |    53   (0)|    100 |00:00:00.01 |     147 |
-------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("ID"=42)

--可以明显看出提示控制了记录返回的行数。

3.再使用SPM看看:

SQL> alter session set optimizer_capture_sql_plan_baselines=true ;
SQL> select * from t2 where id = 100 ;
SQL> select * from t2 where id = 100 ;
SQL> alter session set optimizer_capture_sql_plan_baselines=false ;
SQL> select sql_handle, plan_name, sql_text,enabled, accepted,fixed,origin,signature from dba_sql_plan_baselines ;
SQL_HANDLE                     PLAN_NAME                      SQL_TEXT                                                 ENA ACC FIX ORIGIN                       SIGNATURE
------------------------------ ------------------------------ -------------------------------------------------------- --- --- --- -------------- -----------------------
SYS_SQL_a69226d598cc47a0       SQL_PLAN_ad4j6uqccsjx0b860bcf2 select * from t2 where id = 100                          YES YES NO  AUTO-CAPTURE      12002698655729207200
SQL> select * from t2 where id = 100 ;
        ID NAME
---------- --------------------------------------------------
       100 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
           yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
SQL> @dpc
PLAN_TABLE_OUTPUT
--------------------------------------------------------------
SQL_ID  0n657fnzb9fm0, child number 1
-------------------------------------
select * from t2 where id = 100
Plan hash value: 1513984157
--------------------------------------------------------
| Id  | Operation         | Name | E-Rows | Cost (%CPU)|
--------------------------------------------------------
|   0 | SELECT STATEMENT  |      |        |    53 (100)|
|*  1 |  TABLE ACCESS FULL| T2   |     99 |    53   (0)|
--------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("ID"=100)

--执行计划是全表扫描,并没有选择索引。SPM更多的是稳定计划。它并不知道有很好的执行计划。
--抽取提示看看:

SQL> EXEC dbms_spm.create_stgtab_baseline('stage1');
SQL> variable v_basenum number ;
SQL> EXEC :v_basenum := dbms_spm.pack_stgtab_baseline('stage1', sql_handle => 'SYS_SQL_a69226d598cc47a0');
 
SQL> column comp_data format a100
SQL> select comp_data from stage1 where sql_handle='SYS_SQL_a69226d598cc47a0';
COMP_DATA
----------------------------------------------------------------------------------------------------

1")]]>
![CDATA[OPTIMIZER_FEATURES_ENABLE('11.2.0.1')]]>

SQL> SELECT EXTRACTVALUE (VALUE (h), '.') AS hint
  FROM stage1, TABLE (XMLSEQUENCE (EXTRACT (XMLTYPE (stage1.comp_data), '/outline_data/hint'))) h
 WHERE sql_handle = 'SYS_SQL_a69226d598cc47a0';
HINT
-------------------------------------
FULL(@"SEL$1" "T2"@"SEL$1")
OUTLINE_LEAF(@"SEL$1")
ALL_ROWS
DB_VERSION('11.2.0.1')
OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
IGNORE_OPTIM_EMBEDDED_HINTS
6 rows selected.

--可以发现SPM记录的提示是执行计划,而sql profile记录的提示记录的返回信息。并没有记录执行计划。

4.这样按照上面的提示,如果改变T1表的相关统计信息,执行计划一样会变化:

SQL> select  num_rows from dba_tables where table_name='T1';
  NUM_ROWS
----------
     10001
SQL> exec dbms_stats.set_table_stats(ownname=>user,tabname=>'T1',numrows=>1000001);
PL/SQL procedure successfully completed.
--修改统计信息,行记录增加100倍。
SQL> alter system flush shared_pool;
System altered.
SQL> select * from t1 where id=100;
        ID NAME
---------- --------------------------------------------------
       100 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
           yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
SQL> @dpc
PLAN_TABLE_OUTPUT
-------------------------------------
SQL_ID  c9bya8ajdfsg3, child number 0
-------------------------------------
select * from t1 where id=100
Plan hash value: 3617692013
--------------------------------------------------------
| Id  | Operation         | Name | E-Rows | Cost (%CPU)|
--------------------------------------------------------
|   0 | SELECT STATEMENT  |      |        |    74 (100)|
|*  1 |  TABLE ACCESS FULL| T1   |    100 |    74  (29)|
--------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("ID"=100)
Note
-----
   - SQL profile SYS_SQLPROF_013c6516f3f90000 used for this statement
   - Warning: basic plan statistics not available. These are only collected when:
       * hint 'gather_plan_statistics' is used for the statement or
       * parameter 'statistics_level' is set to 'ALL', at session or system level
25 rows selected.

--可以发现执行计划变成了全表扫描。

5.总结:
    通过对比,可以发现SPM以及sql profile都是为了更好的维护执行计划,但是两者控制的方式,设计理念完全不同。其中的细节留给
大家体会。

 

时间: 2024-07-30 10:47:35

[20130123]spm与sql profile的主要区别在那里.txt的相关文章

Oracle SPM(SQL Plan Management)介绍及演示SQL

Oracle优化器辅助手段的发展 Oracle 8:hint Oracle 8i&9: stored outline Oracle 10: sql profile Oracle 11: sql plan manangement 优化器可能选择到很差的Plan. RBO->CBO 由规则序列生成执行计划,向着智能灵活化发展,根据数据对象的统计信息进行执行计划生成,根据cost选择最优. 但是CBO依赖统计信息,统计量又不能和数据表数据完全同步,当统计信息与实际数据差距大就会导致错误执行计划生成

oracle sql profile实战

第一部分:profile概念 Oracle数据库10g使用了一个叫做SQL配置文件的新方法弥补了存储概要的缺点, DBA可以使用SQL调整顾问(STA)或SQL访问顾问(SAA)来识别可以得到更好性能的SQL语句, 这些语句可以保存在SQL调整集.一个AWR快照或保存在当前的库缓存中,一旦识别出调整候 选者, 这些顾问程序就开始分析捕获到的语句以期获得更好的性能,然后生成专用的语句扩展(就叫 做SQL配置文件)并重写SQL语句以在执行期间获取更佳的性能. 与存储概要类似,一个SQL配置文件提供了

SQL PROFILE的用法详解

一般只需要步骤三.四就可以完成执行计划的修改和固定,而outline和baseline则需要N多个步骤. SQL PROFILE使用简单,不区分大小写,回车,空格,但是对DBA写HINT的能力要求比较高,因为SQL PROFILE要求HINT必须写明查询块名, SQL PROFILE还有其他一些牛逼的特性. 我的示例里教了大家偷懒的做法,但是有时间我们还是最好认真把query block的东西学下. 步骤一-------------------------创建测试表,根据DBA_OBJECTS创

使用SQL Profile进行SQL优化案例

一个社保系统的自助查询系统查询个人医疗费用明细的查询语句要用一分多钟还没查询出来,语句如下: select * from  v_zzzd_ylbx_ylfymxcx where aac002='430703198202280017' 从上面的语句可知是从视图 v_zzzd_ylbx_ylfymxcx中查询数据.v_zzzd_ylbx_ylfymxcx视图的创建语句如下: create or replace view v_zzzd_ylbx_ylfymxcx as select a.indi_id

1223 result cache,sql profile,sql patch

[20141223]result cache 与sql profile,sql patch.txt --前面blog已经提到result cache的好处与缺点,对于第三方优化,sql profile可以改变稳定执行计划,是否可以通过改变提示来稳定 --执行计划,这样对频繁执行的语句较少逻辑读,提高服务器响应有积极意义. --sql patch 也具有相似的作用,看看这种方式是否可行. SCOTT@test> @ver1 PORT_STRING                    VERSIO

[20131122]跟踪sql profile的操作.txt

[20131122]跟踪sql profile的操作.txt sql profile是11G的新特性,前几天我在给别人做优化时,偷懒直接使用toad,step by step分析使用sql profile,导致系统执行缓慢,不得不中断分析.今天有空跟踪sql profile的操作看看,了解一些过程. SCOTT@test> @verBANNER-----------------------------------------------------------------------------

修正执行计划的利器,SQL PROFILE脚本

点击这里下载 sql profile 脚本 profile.sql 我们先来看下如何手工创建sql profile来修正执行计划. 创建两张表test1.test2,在表test2的列object_id 上创建索引,分析两张表. create table test1 as select * from dba_objects; create table test2 as select * from dba_objects; create index test2_oi_ind on test2(ob

一个执行计划异常变更的案例 - 外传之SQL Profile(上)

之前的几篇文章: <一个执行计划异常变更的案例 - 前传> <一个执行计划异常变更的案例 - 外传之绑定变量窥探> <一个执行计划异常变更的案例 - 外传之查看绑定变量值的几种方法> <一个执行计划异常变更的案例 - 外传之rolling invalidation> <一个执行计划异常变更的案例 - 外传之聚簇因子(Clustering Factor)> <一个执行计划异常变更的案例 - 外传之查询执行计划的几种方法> <一个执

一个执行计划异常变更的案例 - 外传之SQL Profile(下)

之前的几篇文章: <一个执行计划异常变更的案例 - 前传> <一个执行计划异常变更的案例 - 外传之绑定变量窥探> <一个执行计划异常变更的案例 - 外传之查看绑定变量值的几种方法> <一个执行计划异常变更的案例 - 外传之rolling invalidation> <一个执行计划异常变更的案例 - 外传之聚簇因子(Clustering Factor)> <一个执行计划异常变更的案例 - 外传之查询执行计划的几种方法> <一个执