Abordando a package DBMS_SQLTUNE para recomendar melhorias em SQL IDs específicos (SQL Tuning Advisor)
Autor: Eduardo Legatti | Publicado: 2016-08-08T11:28:00-03:00

Olá,


 Desde o Oracle 10g, os supervisores (advisors) são ferramentas especializadas que ajudam o DBA a analisar o desempenho do banco de dados, identificar possíveis problemas e gargalos e ajustar os vários componentes do banco de dados. No artigo de Abril/2008 eu demonstrei através de exemplos práticos como fazer para o Oracle analisar instruções SQL específicas e sugerir recomendações para melhorar seu desempenho. Foi usado o Supervisor de Ajuste SQL (SQL Tuning Advisor) através da package DBMS_SQLTUNE. Agora irei abordar novamente o uso do DBMS_SQLTUNE só que, em vez de passar como parâmetro uma instrução SQL para ser analisada, irei passar como parâmetro o SQL_ID de uma instrução SQL que já tinha sido executada anteriormente.

C:\&gt;sqlplus scott/tiger

SQL*Plus: Release 11.2.0.1.0 Production on Seg Ago 8 09:01:22 2016

Copyright (c) 1982, 2010, Oracle.&nbsp; All rights reserved.

Conectado a:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL&gt; var id number;
SQL&gt; exec :id := 2500;

Procedimento PL/SQL concluído com sucesso.

SQL&gt; select count(*) from t1 where id=:id;

&nbsp; COUNT(*)
----------
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8

1 linha selecionada.

 

 Após a execução da instrução SQL acima, irei procurar através da view dinâmica de desempenho V$SQLAREA qual o SQL_ID associado à instrução SQL executada.&nbsp;
&nbsp;&nbsp;  
SQL&gt; select sql_id,parsing_schema_name
  2    from v$sqlarea
  3   where sql_fulltext like 'select count(*) from t1 where id=:id%'; 
SQL_ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PARSING_SCHEMA_NAME
------------- -------------------------
1x6vk95kg44wb SCOTT

1 linha selecionada.


Uma vez encontrada o SQL_ID, irei criar uma tarefa de SQL Tuning passando o SQL_ID 1x6vk95kg44wb e executar a mesma conforme demonstrado a seguir. Para essa tarefa irei limitar a sua execução até o máximo de 5 minutos (300 seg).

SQL&gt; DECLARE
  2    l_sql_tune_task_id  VARCHAR2(100);
  3  BEGIN
  4    l_sql_tune_task_id := DBMS_SQLTUNE.create_tuning_task (
  5                            sql_id      =&gt; '1x6vk95kg44wb',
  6                            scope       =&gt; DBMS_SQLTUNE.scope_comprehensive,
  7                            time_limit  =&gt; 300,
  8                            task_name   =&gt; 'SCOTT_1x6vk95kg44wb',
  9                            description =&gt; 'SCOTT Tuning task for statement 1x6vk95kg44wb.');
 10    DBMS_OUTPUT.put_line('l_sql_tune_task_id: ' || l_sql_tune_task_id);
 11  END;
 12  /
l_sql_tune_task_id: SCOTT_1x6vk95kg44wb

Procedimento PL/SQL concluído com sucesso.

SQL&gt; select task_id,task_name,status from user_advisor_log;

   TASK_ID TASK_NAME                      STATUS
---------- ------------------------------ -----------
     33150 SCOTT_1x6vk95kg44wb            INITIAL

1 linha selecionada.

SQL&gt; exec dbms_sqltune.execute_tuning_task(task_name =&gt; 'SCOTT_1x6vk95kg44wb');

Procedimento PL/SQL concluído com sucesso.




 Pronto. Após a execução será necessário apenas analisar e verificar as recomendações que foram encontradas pelo otimizador. Vale a pena salientar que além de ser mostrado a instrução SQL, também será mostrado o valor da bind variable usada na instrução SQL.

SQL&gt; set long 1000000;
SQL&gt; set longchunksize 100000
SQL&gt; set pagesize 10000
SQL&gt; set linesize 1000
SQL&gt; select dbms_sqltune.report_tuning_task('SCOTT_1x6vk95kg44wb') as recomendacoes from dual;

RECOMENDACOES
--------------------------------------------------------------------------------

GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name&nbsp;&nbsp; : SCOTT_1x6vk95kg44wb
Tuning Task Owner&nbsp; : SCOTT
Workload Type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Single SQL Statement
Scope&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : COMPREHENSIVE
Time Limit(seconds): 300
Completion Status&nbsp; : COMPLETED
Started at&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 08/08/2016 09:13:45
Completed at&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 08/08/2016 09:13:56

-------------------------------------------------------------------------------
Schema Name: SCOTT
SQL ID&nbsp;&nbsp;&nbsp;&nbsp; : 1x6vk95kg44wb
SQL Text&nbsp;&nbsp; : select count(*) from t1 where id=:id
Bind Variables :
&nbsp;1 -&nbsp; (NUMBER):2500

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

1- Statistics Finding
---------------------
&nbsp; A tabela "SCOTT"."T1" não foi analisada.

&nbsp; Recommendation
&nbsp; --------------
&nbsp; - Considere a coleta de estatísticas do otimizador para esta tabela
&nbsp;&nbsp;&nbsp; execute dbms_stats.gather_table_stats(ownname =&gt; 'SCOTT', tabname =&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'T1', estimate_percent =&gt; DBMS_STATS.AUTO_SAMPLE_SIZE, method_opt
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; 'FOR ALL COLUMNS SIZE AUTO');

&nbsp; Rationale
&nbsp; ---------
&nbsp;&nbsp;&nbsp; O otimizador requer estatísticas atualizadas para a tabela ao selecionar
&nbsp;&nbsp;&nbsp; um plano de execução adequado.

2- Index Finding (see explain plans section below)
--------------------------------------------------
&nbsp; O plano de execução dessa instrução pode ser melhorado com a criação de um
&nbsp; ou mais índices.

&nbsp; Recommendation (estimated benefit: 99.93%)
&nbsp; ------------------------------------------
&nbsp; - Considere a execução do Supervisor de Acesso para aumentar o projeto de
&nbsp;&nbsp;&nbsp; esquema físico ou a criação do índice recomendado.
&nbsp;&nbsp;&nbsp; create index SCOTT.IDX$$_817E0001 on SCOTT.T1("ID");

&nbsp; Rationale
&nbsp; ---------
&nbsp;&nbsp;&nbsp; Criar os índices recomendados melhora significativamente o plano de
&nbsp;&nbsp;&nbsp; execução dessa instrução. No entanto, talvez seja preferível executar o
&nbsp;&nbsp;&nbsp; "Supervisor de Acesso" utilizando uma carga de trabalho SQL representativa
&nbsp;&nbsp;&nbsp; em oposição a uma única instrução. Isso permitirá a obtenção de
&nbsp;&nbsp;&nbsp; recomendações de índice abrangentes que levam em consideração o overhead
&nbsp;&nbsp;&nbsp; de manutenção de índice e um consumo de espaço adicional.

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

1- Original
-----------
Plan hash value: 3724264953

---------------------------------------------------------------------------
| Id&nbsp; | Operation&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Name | Rows&nbsp; | Bytes | Cost (%CPU)| Time&nbsp;&nbsp;&nbsp;&nbsp; |
---------------------------------------------------------------------------
|&nbsp;&nbsp; 0 | SELECT STATEMENT&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp; 1 |&nbsp;&nbsp;&nbsp; 13 |&nbsp; 1503&nbsp;&nbsp; (3)| 00:00:19 |
|&nbsp;&nbsp; 1 |&nbsp; SORT AGGREGATE&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp; 1 |&nbsp;&nbsp;&nbsp; 13 |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |
|*&nbsp; 2 |&nbsp;&nbsp; TABLE ACCESS FULL| T1&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp; 73 |&nbsp;&nbsp; 949 |&nbsp; 1503&nbsp;&nbsp; (3)| 00:00:19 |
---------------------------------------------------------------------------

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

&nbsp;&nbsp; 2 - filter("ID"=:ID)

2- Using New Indices
--------------------
Plan hash value: 809122696

------------------------------------------------------------------------------------
| Id&nbsp; | Operation&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; | Rows&nbsp; | Bytes | Cost (%CPU)| Time&nbsp;&nbsp;&nbsp;&nbsp; |
------------------------------------------------------------------------------------
|&nbsp;&nbsp; 0 | SELECT STATEMENT&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp; 1 |&nbsp;&nbsp;&nbsp; 13 |&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp; (0)| 00:00:01 |
|&nbsp;&nbsp; 1 |&nbsp; SORT AGGREGATE&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp; 1 |&nbsp;&nbsp;&nbsp; 13 |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |
|*&nbsp; 2 |&nbsp;&nbsp; INDEX RANGE SCAN| IDX$$_817E0001 |&nbsp;&nbsp;&nbsp;&nbsp; 8 |&nbsp;&nbsp; 104 |&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp; (0)| 00:00:01 |
------------------------------------------------------------------------------------

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

&nbsp;&nbsp; 2 - access("ID"=:ID)

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

1 linha selecionada.