Oracle手工调用STA优化指定SQL

 

Oracle手工调用STA优化指定SQL

环境构造

10:50:58 SYS@zkm(1)> create table scott.zkm as select * from dba_objects;

Table created.

Elapsed: 00:00:01.28
10:51:19 SYS@zkm(1)> set autotrace traceonly
10:52:37 SYS@zkm(1)> create index scott.idx_object_id on scott.zkm(object_id) online;

Index created.

Elapsed: 00:00:01.00

 

目标SQL

select /*+ full(a) */ * from scott.zkm a where object_id=1000;

由于hint的强制关系,该SQL会执行全表扫描,如下:

10:54:24 SYS@zkm(1)> select /*+ full(a) */ * from scott.zkm a where object_id=1000;

Elapsed: 00:00:00.02

Execution Plan
----------------------------------------------------------
Plan hash value: 1571665327

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |   207 |   366   (1)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| ZKM  |     1 |   207 |   366   (1)| 00:00:05 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("OBJECT_ID"=1000)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
          9  recursive calls
          0  db block gets
       1391  consistent gets
       1313  physical reads
          0  redo size
       1628  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

 

查询SQL ID。

col sql_id for a15
set line 500
col sql_text for a100
select sql_id,sql_text from v$sql where sql_text like 'select /*+ full(a) */ * from scott.zkm a where object_id=1000';
模板复制
10:56:56 SYS@zkm(27)> col sql_id for a15
10:57:08 SYS@zkm(27)> set line 500
10:57:11 SYS@zkm(27)> col sql_text for a100
10:57:26 SYS@zkm(27)> select sql_id,sql_text from v$sql where sql_text like 'select /*+ full(a) */ * from scott.zkm a where object_id=1000';

SQL_ID          SQL_TEXT
--------------- ----------------------------------------------------------------------------------------------------
9ajk015s54vpv   select /*+ full(a) */ * from scott.zkm a where object_id=1000

 

跑STA对SQL进行分析。

DECLARE
  a_tuning_task VARCHAR2(30);
BEGIN
  a_tuning_task := dbms_sqltune.create_tuning_task(sql_id    => '9ajk015s54vpv',
                                                   task_name => 'sql_profile_test_SQLID');
  dbms_sqltune.execute_tuning_task(a_tuning_task);
END;
/
模板复制
10:58:40 SYS@zkm(27)> DECLARE
10:58:41   2    a_tuning_task VARCHAR2(30);
10:58:41   3  BEGIN
10:58:41   4    a_tuning_task := dbms_sqltune.create_tuning_task(sql_id    => '9ajk015s54vpv',
10:58:41   5                                                     task_name => 'sql_profile_test_SQLID');
10:58:41   6    dbms_sqltune.execute_tuning_task(a_tuning_task);
10:58:41   7  END;
10:58:41   8  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:02.56

或者:

DECLARE
  a_tuning_task VARCHAR2(30);
BEGIN
  a_tuning_task := dbms_sqltune.create_tuning_task(sql_text    => 'select /*+ full(a) */ * from scott.zkm a where object_id=1000',
                                                   task_name => 'sql_profile_test_SQLID');
  dbms_sqltune.execute_tuning_task(a_tuning_task);
END;
/

 

 

使用PLSQL工具查看优化建议报告(用sqlplus格式会乱)。

SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK( 'sql_profile_test_SQLID') from DUAL;

GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name   : sql_profile_test_SQLID
Tuning Task Owner  : SYS
Workload Type      : Single SQL Statement
Scope              : COMPREHENSIVE
Time Limit(seconds): 1800
Completion Status  : COMPLETED
Started at         : 09/01/2020 10:58:42
Completed at       : 09/01/2020 10:58:44

-------------------------------------------------------------------------------
Schema Name: SYS
SQL ID     : 9ajk015s54vpv
SQL Text   : select /*+ full(a) */ * from scott.zkm a where object_id=1000

-------------------------------------------------------------------------------
FINDINGS SECTION (2 findings)
-------------------------------------------------------------------------------

1- Statistics Finding
---------------------
  Table "SCOTT"."ZKM" was not analyzed.

  Recommendation
  --------------
  - Consider collecting optimizer statistics for this table.
    execute dbms_stats.gather_table_stats(ownname => 'SCOTT', tabname =>
            'ZKM', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
            method_opt => 'FOR ALL COLUMNS SIZE AUTO');

  Rationale
  ---------
    The optimizer requires up-to-date statistics for the table in order to
    select a good execution plan.

2- SQL Profile Finding (see explain plans section below)
--------------------------------------------------------
  A potentially better execution plan was found for this statement.

  Recommendation (estimated benefit: 99.77%)
  ------------------------------------------
  - Consider accepting the recommended SQL profile.
    execute dbms_sqltune.accept_sql_profile(task_name =>
            'sql_profile_test_SQLID', task_owner => 'SYS', replace => TRUE);

  Validation results
  ------------------
  The SQL profile was tested by executing both its plan and the original plan
  and measuring their respective execution statistics. A plan may have been
  only partially executed if the other could be run to completion in less time.

                           Original Plan  With SQL Profile  % Improved
                           -------------  ----------------  ----------
  Completion Status:            COMPLETE          COMPLETE
  Elapsed Time (s):             .002195           .000006      99.72 %
  CPU Time (s):                 .002092           .000006      99.71 %
  User I/O Time (s):                  0                 0 
  Buffer Gets:                     1318                 3      99.77 %
  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. Statistics for the original plan were averaged over 10 executions.
  2. Statistics for the SQL profile plan were averaged over 10 executions.

-------------------------------------------------------------------------------
EXPLAIN PLANS SECTION
-------------------------------------------------------------------------------

1- Original With Adjusted Cost
------------------------------
Plan hash value: 1571665327

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     2 |   206 |   366   (1)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| ZKM  |     2 |   206 |   366   (1)| 00:00:05 |
--------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("OBJECT_ID"=1000)

2- Using SQL Profile
--------------------
Plan hash value: 3532417104

---------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |     2 |   206 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| ZKM           |     2 |   206 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IDX_OBJECT_ID |     2 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("OBJECT_ID"=1000)

-------------------------------------------------------------------------------
优化报告

 

根据优化报告,

第一个建议是收集统计信息:

1- Statistics Finding
---------------------
  Table "SCOTT"."ZKM" was not analyzed.

  Recommendation
  --------------
  - Consider collecting optimizer statistics for this table.
    execute dbms_stats.gather_table_stats(ownname => 'SCOTT', tabname =>
            'ZKM', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
            method_opt => 'FOR ALL COLUMNS SIZE AUTO');

  Rationale
  ---------
    The optimizer requires up-to-date statistics for the table in order to
    select a good execution plan.

 

第二个建议你使用sql profile固定执行计划,是使用索引的执行计划:

2- SQL Profile Finding (see explain plans section below)
--------------------------------------------------------
  A potentially better execution plan was found for this statement.

  Recommendation (estimated benefit: 99.77%)
  ------------------------------------------
  - Consider accepting the recommended SQL profile.
    execute dbms_sqltune.accept_sql_profile(task_name =>
            'sql_profile_test_SQLID', task_owner => 'SYS', replace => TRUE);

2- Using SQL Profile
--------------------
Plan hash value: 3532417104

---------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |     2 |   206 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| ZKM           |     2 |   206 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IDX_OBJECT_ID |     2 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("OBJECT_ID"=1000)

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

 

执行建议

  1. execute dbms_stats.gather_table_stats(ownname => 'SCOTT', tabname => 'ZKM', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,method_opt => 'FOR ALL COLUMNS SIZE AUTO');
  2. execute dbms_sqltune.accept_sql_profile(task_name => 'sql_profile_test_SQLID', task_owner => 'SYS', replace => TRUE);
11:27:16 SYS@zkm(23)> execute dbms_stats.gather_table_stats(ownname => 'SCOTT', tabname => 'ZKM', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,method_opt => 'FOR ALL COLUMNS SIZE AUTO');

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.49
11:27:31 SYS@zkm(23)> execute dbms_sqltune.accept_sql_profile(task_name => 'sql_profile_test_SQLID', task_owner => 'SYS', replace => TRUE);

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.21

 

再次执行SQL,已经使用了索引:

11:28:23 SYS@zkm(1)> select /*+ full(a) */ * from scott.zkm a where object_id=1000;

Elapsed: 00:00:00.03

Execution Plan
----------------------------------------------------------
Plan hash value: 3532417104

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

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("OBJECT_ID"=1000)

Note
-----
   - SQL profile "SYS_SQLPROF_017447b4e5170000" used for this statement


Statistics
----------------------------------------------------------
         36  recursive calls
          0  db block gets
         15  consistent gets
          1  physical reads
          0  redo size
       1631  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

从这里可以看出,SQL profile的优先级高于HINT。

 

回退

若是发现应用建议后,没有改善情况或者情况恶化,可以如下回退:

col name for a35
col sql_text for a100
set line 500
select name,SQL_TEXT,STATUS from dba_sql_profiles;
模板复制
11:33:54 SYS@zkm(27)> col name for a35
11:34:00 SYS@zkm(27)> col sql_text for a100
11:34:06 SYS@zkm(27)> set line 500
11:34:08 SYS@zkm(27)> select name,SQL_TEXT,STATUS from dba_sql_profiles;

NAME                                SQL_TEXT                                                                                             STATUS
----------------------------------- ---------------------------------------------------------------------------------------------------- ------------------------
SYS_SQLPROF_017447b4e5170000        select /*+ full(a) */ * from scott.zkm a where object_id=1000                                        ENABLED



Elapsed: 00:00:00.00

11:34:39 SYS@zkm(27)> execute dbms_sqltune.drop_sql_profile('SYS_SQLPROF_017447b4e5170000');

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.01

11:34:52 SYS@zkm(1)> select /*+ full(a) */ * from scott.zkm a where object_id=1000;

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
Plan hash value: 1571665327

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    98 |   366   (1)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| ZKM  |     1 |    98 |   366   (1)| 00:00:05 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
exec dbms_sqltune.execute_tuning_task('SYS_AUTO_SQL_TUNING_TASK');
select dbms_sqltune.report_tuning_task('SYS_AUTO_SQL_TUNING_TASK') from dual;

 

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

   1 - filter("OBJECT_ID"=1000)


Statistics
----------------------------------------------------------
          5  recursive calls
          0  db block gets
       1319  consistent gets
          0  physical reads
          0  redo size
       1628  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

 

暂时禁用

begin
dbms_sqltune.alter_sql_profile(name => 'SYS_SQLPROF_0177dbccd9090000',
attribute_name => 'status',
value => 'disabled');
end;
/

删除STA任务

最后记得删除STA任务。

11:34:53 SYS@zkm(1)> exec dbms_sqltune.drop_TUNING_TASK( 'sql_profile_test_SQLID');

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.05

 

其他

对于系统每日自动运行的STA任务,如果不需要可以禁用,必要时可以手工运行。

exec dbms_sqltune.execute_tuning_task('SYS_AUTO_SQL_TUNING_TASK');
select dbms_sqltune.report_tuning_task('SYS_AUTO_SQL_TUNING_TASK') from dual;
select DBMS_SQLTUNE.REPORT_SQL_DETAIL(sql_id=>'9ajk015s54vpv',report_level=> 'ALL') from dual;

https://docs.oracle.com/database/121/ARPLS/d_sqltun.htm#ARPLS72953

 

posted @ 2020-09-01 11:29  PiscesCanon  阅读(404)  评论(0编辑  收藏  举报