Oracle sqlprofile 偷梁换柱

注:测试环境 win7+oracle10.2.0.4

基础知识:

STA—sql tuning advisor;

使用sqlprofile 时需要创建 sql tuning task,也就是说要先搞清楚 sta 的使用情况,下面来看看sta 的使用

Sta 的使用可以通过em完成,也可以通过oracle db中的 dbms_sqltue完成;我比较习惯后者;dbms_sqltune的使用主要分为两步:

—创建sql tuning task

—执行 sql tuning task

来看一个简单的实例:

SQL> desc emp 名称                                                  是否为空? 类型 —————————————————– ——– EMPNO                                                 NOT NULL NUMBER(4) ENAME                                                          VARCHAR2(10) JOB                                                            VARCHAR2(9) MGR                                                            NUMBER(4) HIREDATE                                                       DATE SAL                                                            NUMBER(7,2) COMM                                                           NUMBER(7,2) DEPTNO                                                         NUMBER(2)SQL> show userUSER 为 “SCOTT”SQL> DECLARE  2    huosi_task1 VARCHAR2(30);  3    huosi_txt1 CLOB;  4  BEGIN  5    huosi_txt1 := ‘SELECT * ‘   ||  6                  ‘FROM EMP ‘ || ‘WHERE EMPNO=7369′ ;  7    huosi_task1 := DBMS_SQLTUNE.CREATE_TUNING_TASK(  8                             sql_text => huosi_txt1,  9                             user_name => ‘SCOTT’, 10                             scope => ‘COMPREHENSIVE’, 11                             time_limit => 60, 12                             task_name => ‘test_task1′, 13                             description => ‘first test task’); 14  END; 15  /PL/SQL 过程已成功完成。SQL> Execute dbms_sqltune.Execute_tuning_task (task_name => ‘test_task1′);PL/SQL 过程已成功完成。SQL> select status from dba_advisor_log where task_name=’test_task1′;STATUS———————-COMPLETEDSQL> set long 65536SQL> set longchunksize 65536SQL> set linesize 100SQL> select dbms_sqltune.report_tuning_task(‘test_task1′) from dual  2  ;SQL>

注意此时没有返回数据的原因是,sqlplus 不显示lob数据,可以plsql查看,如图:

GENERAL INFORMATION SECTION——————————————————————————-Tuning Task Name                  : test_task1Tuning Task Owner                 : SCOTTScope                             : COMPREHENSIVETime Limit(seconds)               : 60Completion Status                 : COMPLETEDStarted at                        : 05/29/2012 10:35:39Completed at                      : 05/29/2012 10:35:40Number of Statistic Findings      : 1——————————————————————————-Schema Name: SCOTTSQL ID     : 31qp81kj64a38SQL Text   : SELECT * FROM EMP WHERE EMPNO=7369——————————————————————————-FINDINGS SECTION (1 finding)——————————————————————————-1- Statistics Finding———————  表 “SCOTT”.”EMP” 及其索引的优化程序统计信息已失效。  Recommendation  ————–  – 考虑收集此表的优化程序统计信息。    execute dbms_stats.gather_table_stats(ownname => ‘SCOTT’, tabname =>            ‘EMP’, estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,            method_opt => ‘FOR ALL COLUMNS SIZE AUTO’);  Rationale  ———    为了选择好的执行计划, 优化程序需要此表的最新统计信息。——————————————————————————-EXPLAIN PLANS SECTION——————————————————————————-1- Original———–Plan hash value: 2949544139————————————————————————————–| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |————————————————————————————–|   0 | SELECT STATEMENT            |        |     1 |    32 |     1   (0)| 00:00:01 ||   1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    32 |     1   (0)| 00:00:01 ||*  2 |   INDEX UNIQUE SCAN         | PK_EMP |     1 |       |     0   (0)| 00:00:01 |————————————————————————————–Predicate Information (identified by operation id):—————————————————   2 – access(“EMPNO”=7369)——————————————————————————-

到这里 STA 的基本使用就完成了;

Sql profile :

Sql profile 是10g 的一个新特性,可以通过em 也可以通过dbms_sqltune进行管理;

Sql profile 本身是存储在数据字典中的信息的一个集合,这些信息可以被cob使用,以使优化器能够生成一个更优化的执行计划;profile中的信息能够改善优化器中的cardinality和selectivity,从而使优化器能够选择更好的执行计划;

当时sql profile 并不包括单个的执行计划的信息,当优化器选择执行计划时它本身会包含以下的信息:

  •   The environment, which contains the database configuration, bind variable values, optimizer statistics, data set, and so on
  • The supplemental statistics in the SQL profile

Sql profile 本身并不会像 outline一样固定一个sql 的执行计划,比如当数据量发生变化时执行计划可能就会变化;能够应用sql profile 的语句包括:

SELECT statements
UPDATE statements
INSERT statements (only with a SELECT clause)
DELETE statements
CREATE TABLE statements (only with the AS SELECT clause)
MERGE statements (the update or insert operations)

在10g当中,oracle CBO的功能进一步加强,也就是说oracle 的优化器会根据系统的统计信息、sqlprofile等来自动选择执行计划,比如在某些情况下优化器会跳过hint;

下面来看看 sqlprofile是如何偷梁换柱,避开hint 的;

SQL> show userUSER 为 “SCOTT”SQL> create table test_sp(n number);表已创建。SQL> declare  2            begin  3             for i in 1 .. 10000 loop  4                 insert into test_sp values(i);  5                 commit;  6             end loop;  7            end;  8  /PL/SQL 过程已成功完成。

 

SQL> create index test_idx on test_sp(n);索引已创建。SQL> exec dbms_stats.gather_table_stats(”,’TEST_SP’);PL/SQL 过程已成功完成。SQL> set autotrace onSQL> select /*+ no_index(test_sp test_idx) */ * from test_sp where n=1  2  ;         N———-         1执行计划———————————————————-Plan hash value: 3988747878—————————————————————————–| Id  | Operation         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |—————————————————————————–|   0 | SELECT STATEMENT  |         |     1 |     3 |     7   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| TEST_SP |     1 |     3 |     7   (0)| 00:00:01 |—————————————————————————–Predicate Information (identified by operation id):—————————————————   1 – filter(“N”=1)统计信息———————————————————-          1  recursive calls          0  db block gets         24  consistent gets          0  physical reads          0  redo size        412  bytes sent via SQL*Net to client        400  bytes received via SQL*Net from client          2  SQL*Net roundtrips to/from client          0  sorts (memory)          0  sorts (disk)          1  rows processedSQL>

此时可以看出 sql是进行的全表扫描;

重新开启一个会话:

SQL> declare  2    my_task_name VARCHAR2(30);  3    my_sqltext CLOB;  4    begin  5       my_sqltext := ‘select /*+ no_index(test_sp test_idx) */ * from test_sp where n=1′;  6       my_task_name := DBMS_SQLTUNE.CREATE_TUNING_TASK(  7       sql_text => my_sqltext,  8       user_name => ‘SCOTT’,  9       scope => ‘COMPREHENSIVE’, 10       time_limit => 60, 11       task_name => ‘my_sql_tuning_task_3′, 12       description => ‘Task to tune a query on a specified table’); 13  end; 14  /PL/SQL 过程已成功完成。SQL> begin  2  DBMS_SQLTUNE.EXECUTE_TUNING_TASK( task_name => ‘my_sql_tuning_task_3′);  3  end;  4  /PL/SQL 过程已成功完成。SQL>

看看 sqlprofile的信息;

GENERAL INFORMATION SECTION——————————————————————————-Tuning Task Name                  : my_sql_tuning_task_3Tuning Task Owner                 : SYSScope                             : COMPREHENSIVETime Limit(seconds)               : 60Completion Status                 : COMPLETEDStarted at                        : 05/29/2012 11:32:13Completed at                      : 05/29/2012 11:32:13Number of SQL Profile Findings    : 1——————————————————————————-Schema Name: SCOTTSQL ID     : 1ks8q8x9ttbbySQL Text   : select /*+ no_index(test_sp test_idx) */ * from test_sp where n=1

 

——————————————————————————-FINDINGS SECTION (1 finding)——————————————————————————-1- SQL Profile Finding (see explain plans section below)——————————————————–  为此语句找到了性能更好的执行计划。  Recommendation (estimated benefit: 86.4%)  —————————————–  – 考虑接受推荐的 SQL 概要文件。    execute dbms_sqltune.accept_sql_profile(task_name =>            ‘my_sql_tuning_task_3′, replace => TRUE);——————————————————————————-EXPLAIN PLANS SECTION——————————————————————————-1- Original With Adjusted Cost——————————Plan hash value: 3988747878—————————————————————————–| Id  | Operation         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |—————————————————————————–|   0 | SELECT STATEMENT  |         |     1 |     3 |     7   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| TEST_SP |     1 |     3 |     7   (0)| 00:00:01 |—————————————————————————–

 

Predicate Information (identified by operation id):—————————————————   1 – filter(“N”=1)2- Using SQL Profile——————–Plan hash value: 2882402178—————————————————————————–| Id  | Operation        | Name     | Rows  | Bytes | Cost (%CPU)| Time     |—————————————————————————–|   0 | SELECT STATEMENT |          |     1 |     3 |     1   (0)| 00:00:01 ||*  1 |  INDEX RANGE SCAN| TEST_IDX |     1 |     3 |     1   (0)| 00:00:01 |—————————————————————————–Predicate Information (identified by operation id):—————————————————   1 – access(“N”=1)——————————————————————————-
SQL> DECLARE2  my_sqlprofile_name VARCHAR2(30);

3  begin

4  my_sqlprofile_name := DBMS_SQLTUNE.ACCEPT_SQL_PROFILE (

5  task_name => ‘my_sql_tuning_task_3′,

6  name => ‘my_sql_profile’);

7  end;

8  /

PL/SQL 过程已成功完成。

SQL>

此时再次执行查询语句:

SQL> select /*+ no_index(test_sp test_idx) */ * from test_sp where n=1;

 

         N———-         1执行计划———————————————————-Plan hash value: 2882402178—————————————————————————–| Id  | Operation        | Name     | Rows  | Bytes | Cost (%CPU)| Time     |—————————————————————————–|   0 | SELECT STATEMENT |          |     1 |     3 |     1   (0)| 00:00:01 ||*  1 |  INDEX RANGE SCAN| TEST_IDX |     1 |     3 |     1   (0)| 00:00:01 |—————————————————————————–Predicate Information (identified by operation id):—————————————————   1 – access(“N”=1)Note—–   – SQL profile “my_sql_profile” used for this statement统计信息———————————————————-          1  recursive calls          0  db block gets          3  consistent gets          0  physical reads          0  redo size        412  bytes sent via SQL*Net to client        400  bytes received via SQL*Net from client          2  SQL*Net roundtrips to/from client          0  sorts (memory)          0  sorts (disk)          1  rows processedSQL>

此时sql的执行已经跳开了hint,开始使用索引,也就是说现在优化器选择一个比hint更优的执行计划

此时再次修改下 sql:

SQL> select /*+ no_index(test_sp test_idx) */ * from test_sp where n=2;

 

         N———-         2执行计划———————————————————-Plan hash value: 3988747878—————————————————————————–| Id  | Operation         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |—————————————————————————–|   0 | SELECT STATEMENT  |         |     1 |     3 |     7   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| TEST_SP |     1 |     3 |     7   (0)| 00:00:01 |—————————————————————————–Predicate Information (identified by operation id):—————————————————   1 – filter(“N”=2)统计信息———————————————————-          1  recursive calls          0  db block gets         24  consistent gets          0  physical reads          0  redo size        412  bytes sent via SQL*Net to client        400  bytes received via SQL*Net from client          2  SQL*Net roundtrips to/from client          0  sorts (memory)          0  sorts (disk)          1  rows processedSQL>

可以发现,此时sql执行的仍旧为全表扫描,仅仅是将1变成了2,sqlprofile 就失去作用;

 

那么对于此种literal sql 是否可以使用相同的sql profile呢,答案是肯定的,下面演示下:

SQL> execute dbms_sqltune.accept_sql_profile(task_name =>’my_sql_tuning_task_3′, replace => TRUE, force_match=>true);PL/SQL 过程已成功完成。

此时sql profile将启用force match,其作用类型crsor_sharing 的force设置;

此时再次执行sql(scott):

SQL> select /*+ no_index(test_sp test_idx) */ * from test_sp where n=2;         N———-         2执行计划———————————————————-Plan hash value: 2882402178—————————————————————————–| Id  | Operation        | Name     | Rows  | Bytes | Cost (%CPU)| Time     |—————————————————————————–|   0 | SELECT STATEMENT |          |     1 |     3 |     1   (0)| 00:00:01 ||*  1 |  INDEX RANGE SCAN| TEST_IDX |     1 |     3 |     1   (0)| 00:00:01 |—————————————————————————–Predicate Information (identified by operation id):—————————————————   1 – access(“N”=2)Note—–   – SQL profile “SYS_SQLPROF_014de5abcc24c000″ used for this statement统计信息———————————————————-          1  recursive calls          0  db block gets          3  consistent gets          0  physical reads          0  redo size        412  bytes sent via SQL*Net to client        400  bytes received via SQL*Net from client          2  SQL*Net roundtrips to/from client          0  sorts (memory)          0  sorts (disk)          1  rows processedSQL>

此时可以看出sql 已经开始使用索引;

通过以上的简单例子可以发现对sql profile可以帮助用来更好的优化sql,所以掌握sql profile 是非常有必要的;

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25656398/viewspace-731367/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/25656398/viewspace-731367/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值