quinta-feira, 28 de novembro de 2013

Plano de execução

Plano de execução
Fonte:
http://www.fabioprado.net/2011/03/analisando-o-plano-de-execucao-para.html

Analisando o Plano de Execução para tunar instruções SQL

Olá Pessoal,
  
     No artigo de hoje irei comentar sobre o que é o Plano de Execução (no Oracle Database) e como utilizá-lo para nos a ajudar a tunar queries, e consequentemente, criarmos aplicações com melhor desempenho.
  
     O Plano de Execução de uma instrução SQL é uma sequência de operações que o Banco de Dados (BD) Oracle realiza para executar uma instrução. Ele é exibido em forma de uma árvore de linhas, que representam passos e que contém as seguintes informações:
  
       - Ordenação das tabelas referenciadas pela instrução;
       - Método de acesso para cada tabela mencionada na instrução;
       - Método join para as tabelas afetadas pelas operações join da instrução;
       - Operações de dados tais como filter, sort ou agregação;
       - Otimização: custo e cardinalidade de cada operação;
       - Particionamento: conjunto de partições acessadas;
       - Se a instrução utilizará execução paralela etc.
  
     O Plano de Execução pode mudar conforme o ambiente em que está sendo executado. Ele pode mudar se for executado em schemas diferentes ou ambientes de Bancos de Dados com custos (volume de dados e estatísticas, parâmetros de servidor ou sessão etc.) diferentes.
  
     Os resultados de um plano de execução permitem visualizar as decisões do Otimizador de Query do Oracle  e analisar a performance de uma query. Através dele é possível verificar se uma query acessa dados através de full table scan (°) ou index lookup (¹), e até mesmo, qual tipo de join ela efetuou: um nested loops join (²) ou um hash join (³).
(°) Full table scan: Caminho de acesso em que os dados são recuperados percorrendo todas as linhas de uma tabela. É mais eficiente para recuperar uma grande quantidade de dados da tabela. 
(¹) Index Lookup: Caminho de acesso em que os dados são recuperados através do uso de índices. É mais eficiente para recuperar um pequeno conjunto de linhas da tabela. 
(²) Nested loop join: Método de acesso de ligação (join) entre 2 tabelas ou origens de dados, utilizado quando pequenos conjuntos de dados estão sendo ligados e se a condição de ligação é um caminho eficiente para acessar a segunda tabela. 
(³) Hash join: Método de acesso de ligação (join) entre 2 tabelas ou origens de dados, utilizado para ligar grandes conjuntos de dados.
 
     O Plano de Execução, por si só, não pode diferenciar instruções SQL bem tunadas (mais otimizadas) daquelas que não apresentam boa performance. O acesso a dados por meio de índices normalmente é mais rápido que acesso full table scan, em ambientes OLTP, porém o fato do Plano de Execução utilizar um índice em algum passo da execução não necessariamente significa que a instrução será executada eficientemente. Em alguns casos, índices podem ser extremamente ineficientes. Segundo a Oracle, quando uma consulta irá retornar mais que 4% dos dados de uma ou mais tabelas ou quando uma consulta irá acessar tabelas pequenas (com poucas linhas), geralmente é mais rápido o acesso full table scan do que o acesso index lookup.
  
     Para analisar o Plano de Execução de uma instrução SQL pode-se utilizar o comando EXPLAIN PLAN, que permite exibir um plano escolhido pelo otimizador de queries do Oracle, para executar as instruções  SQL. Ao executá-lo, o otimizador escolhe um plano de execução e insere os dados descrevendo este plano em uma tabela do BD chamada PLAN_TABLE (é possível também gravar em outras tabelas). Para analisar o plano de execução é necessário escrever uma consulta para pesquisar essa tabela (SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
     Segue abaixo a Imagem 01, com um exemplo de como usar o EXPLAIN PLAN para ver os seus resultados e analisar o plano de execução de uma instrução SQL:


Imagem 01 - Exemplo de um plano de execução
                  
                 Obs.: Se no resultado (PLAN_TABLE_OUTPUT)  você não visualizar a coluna Time, conecte-se no BD através do SQL Plus e execute os comando(s) e script(s) abaixo:
       
                      drop table plan_table purge;
                      commit;
                      @$ORACLE_HOME/rdbms/admin/catplan.sql -- exemplo considerando SO Linux. Substitua $ORACLE_HOME pelo diretório correspondente ao Oracle Home do BD. 

      
     Seguem abaixo algumas regras gerais para analisar um plano de execução:
          - Em geral, a ordem de execução tem início na linha que está identada mais para a direita, seguindo a ordem do primeiro filho do nó raiz da árvore (para compreender melhor este item, consulte as referências ao final do artigo);
          -  O próximo passo a ser executado é o pai da linha encontrada no passo anterior, ou seja, a linha que está identada no nível à esquerda mais próximo;
          -  Se 2 linhas estão identadas igualmente (no mesmo nível), a linha mais acima é executada primeiro;
          -  Avalie as operações que estão sendo executadas (coluna Operation) e as estatísticas dessas operações: a quantidade de bytes (coluna Bytes) e o custo (coluna Cost) de cada passo ou simplesmente o tempo de resposta das operações (coluna Time). 
 
     Para tunar uma query, altere uma instrução SQL inúmeras vezes, analise o plano de execução de cada versão que foi alterada e opte por implementar aquela versão que consome menos recursos (colunas Bytes e Cost (%CPU)) ou que apresenta menor tempo de resposta (coluna Time). Verifique também se as operações que estão sendo executadas em cada passo do plano de execução são adequadas para a quantidade de dados a ser retornada. Se não forem adequadas, quando por exemplo no caso das estatísticas das tabelas acessadas não estarem atualizadas, é possível forçar uma operação que possa ser mais performática através do uso de hints.


CONCLUSÃO

  
   De um modo geral não é muito difícil analisar um plano de execução quando você conhece as operações  estatísticas que podem estar contidas nele e as regras gerais para que você possa analisá-lo. 
  
   É importante entender que o Plano de Execução é uma estimativa e não o tempo real de execução da query, e que os seus passos e estatísticas podem variar se a instrução SQL for executada em ambientes diferentes (Ex.: Produção e Homologação).

   O problema maior ao analisar um plano de execução é que pode ser muito trabalhoso analisar o plano de uma instrução SQL longa e complexa  (você pode demorar muitas horas para entender o que ela irá fazer), portanto, para aumentar a sua produtividade, é importante entender os pontos principais que devem ser sempre analisados.

TKPRO - SQL TRACE 2

Analisando SQL traces em Bancos de Dados Oracle - Parte 1 

Fonte:
http://www.fabioprado.net/2013/09/analisando-traces-em-bancos-de-dados.html
http://www.fabioprado.net/2013/09/analisando-sql-traces-em-bancos-de.html

  O objetivo principal deste artigo, é deixar claro (de um modo resumido) que existem N formas de gerar SQL trace, o porquê de eu escolher 1 delas, e como analisar os pontos principais de um trace para analisar o desempenho de uma instrução SQL.

    Antes de começar, é importante entender, que existem outros tipos de trace e que abordaremos aqui apenas o trace de instruções SQL. Para facilitar a compreensão, sempre que eu citar trace de forma indefinida dentro do artigo, estarei me referindo à SQL trace, ou seja, trace de instruções SQL. Analisar um trace é um dos métodos mais utilizados para entender em detalhes como uma instrução SQL foi executada no BD e efetuar Debug! 



1- Como uma instrução SQL é executada dentro do BD?
     Toda instrução SQL pode ser executada em um BD Oracle em até 3 passos:  
          a) Parse:
            Primeira fase da execução. Nesta fase o Otimizador do Oracle analisa basicamente a sintaxe e a semântica da instrução SQL e monta um plano de execução para ela. 
          b) Execute:
            Segunda fase da execução. Esta é a fase em que o Otimizador realmente executa a instrução SQL, conforme o plano de execução montado no estágio anterior.
          c) Fetch:
            Última fase da execução, única que não é obrigatória. Nesta fase o Otimizador retorna os dados para a sessão de usuário e isso só ocorre em instruções SELECT.

     Toda instrução SQL que é executada em um BD deve ter no mínimo 1 Parse e 1 Execute. O ideal é que ela tenha 1 Parse e N Executes, e isso só ocorre quando a instrução SQL é executada sempre com a mesma string, com variáveis bind ou com o recurso de compartilhamento de cursores habilitado. 
.
Imagem 01 - Fases da da execução de uma instrução SQL
Fonte: Oracle Corporation
     
2- O que é um arquivo trace?
     Trace ou especificamente SQL Trace, é um método de rastreamento de comandos SQL para verificar o que está sendo executado no BD e pode ser utilizado para corrigir erros (debug) ou otimizar SQL. No Oracle Database, o SQL Trace pode ser habilitado no nível de sessão (identificador do cliente, serviço, módulo ou ação) ou BD. Ao habilitar SQL Trace na sessão de um usuário, todas as instruções SQL que ele submeter ao BD serão registradas em um arquivo, comumente conhecido como arquivo trace. As principais informações que um arquivo trace contém são:
     - Contadores de parse, fetch e execute;
     - Tempo de CPU e o tempo total de execução de instruções SQL;
     - Quantidade de leituras físicas e lógicas;
     - Quantidade de linhas processadas.

     Os arquivos trace possuem um nome composto pelas seguintes partes: nome da instância + "_" + nome do processo de background + "_" + valor numérico + "." + extensão .trc 
(Ex.: orcl_mmon_27214.trc). Eles podem ser gerados em pastas diferentes, conforme a versão do Oracle Database. Para descobrir facilmente onde eles são gerados, execute no BD (conectado com um usuário que tenha privilégios de administrador), a consulta abaixo:
     SQL> show parameter background_dump_dest

     A pasta retornada no comando acima contém arquivos trace de processos de usuário e background. Trace de processos de background são gerados automaticamente pelo Oracle Database, quando ele encontra algum problema no BD. Para identificar mais facilmente os arquivos traces de usuário, pode-se acrescentar prefixos aos nomes dos arquivos, configurando-se o parâmetro TRACEFILE_IDENTIFIER (mais adiante veremos isso). Outro ponto importante a ser considerado antes de gerar traces, é o tamanho máximo de um arquivo trace, que pode ser configurado através do parâmetro MAX_DUMP_FILE_SIZE (também veremos isso adiante).



3- Como gerar um arquivo trace?

    Atualmente (até a versão 12C do Oracle Database), existem 6 métodos para habilitar SQL Trace no BD:

          1- ORADEBUG:
       É uma ferramenta de debug muito poderosa, que passou a existir na versão 8.1 do Oracle Database. Ela não é muito bem documentada e por questões de segurança, recomenda-se utilizá-la somente quando o suporte da Oracle indicar. Por existirem outros métodos atuais mais seguros que substituem esta ferramenta para gerar sql trace, não irei abordá-la. Para obter mais informações sobre oradebug, consulte o link a seguir: Oradebug.
 
          2- Parâmetro SQL_TRACE:
         Este é o método mais simples de habilitar SQL Trace e pode ser realizado configurando-se o parâmetro SQL_TRACE no nível da instância (ALTER SYSTEM) ou sessão (ALTER SESSION). Por questões de performance do BD (trace consome muitos recursos do BD), jamais habilite este parâmetro no nível da instância em um ambiente de produção. Execute os comandos do roteiro abaixo na sessão de um usuário que você deseja habilitar o trace:
  
       a) Configurando um prefixo no nome do arquivo trace:
     SQL> alter session set tracefile_identifier='hr_';

       b) Configurando o tamanho máximo de um arquivo trace, também conhecido como trace dump:
     SQL> alter session set max_dump_file_size=UNLIMITED;
  
Obs.: O parâmetro MAX_DUMP_FILE_SIZE tem por padrão o valor UNLIMITED a partir da versão 8.1.6 do Oracle Database, o que significa que podemos gerar traces com tamanho ilimitado. Quando instruções SQL não estiverem aparecendo em um arquivo trace, verifique se não é o valor deste parâmetro que está limitando o tamanho do arquivo, e por este motivo, suprimindo os SQLs que você está procurando. 

       c) Iniciando a geração de trace simples:
     SQL> alter session set sql_trace=TRUE;
  
     ou:

    c) Iniciando a geração de trace de um trace estendido (que nada mais é do que um trace contendo informações adicionais, que podem incluir Wait Events e Bind Variables):
     SQL> alter session set events '10046 trace name context forever, level 12';
     Depois de habilitar o trace e executar as instruções SQL que você quer investigar, não esqueça de desabilitar o trace. Para desabilitar o trace simples, execute o comando abaixo:
     SQL> alter session set sql_trace=FALSE;
       ou, para desabilitar o trace estendido, execute:
     SQL> alter session set events '10046 trace name context off';

Obs.: Como todo parâmetro configurado em nível de sessão, os valores configurados são descartados ao efetuar logoff.
          3- Package DBMS_SUPPORT
          Esta package foi introduzida provavelmente no Oracle 8.1.7 e não vem instalada por padrão no BD. Para instalá-la, é necessário executar o script $ORACLE_HOME/rdbms/admin/dbmssupp.sql. A package DBMS_SUPPORT permite habilitar SQL Trace somente no nível da sessão (similar ao ALTER SESSION SET SQL_TRACE...), portanto, ela é mais limitada que as opções anteriores (que permitem habilitar trace no nível da instância).
    
     Para habilitar a geração de um trace estendido, execute o comando abaixo:
     SQL> BEGIN DBMS_SUPPORT.START_TRACE(true, true); END;
   
     Para desabilitar a geração de trace estendido, execute o comando abaixo:
     SQL> BEGIN DBMS_SUPPORT.STOP_TRACE; END;
          4- Package DBMS_SESSION
          Esta package foi introduzida provavelmente no Oracle 9i e é mais poderosa que as opções anteriores, pois possui recursos adicionais para habilitar trace em grupos de sessões, permitindo simplificar, por exemplo, a geração de traces na conta de um usuário que possui um pool de conexões. Para gerenciar o trace de múltiplas sessões, é necessário configurar um identificador de cliente único ao iniciar cada sessão (ver DBMS_SESSION.SET_IDENTIFIER).
  
     Para habilitar a geração de um trace, execute o comando abaixo:
     SQL> BEGIN DBMS_SESSION.SET_SQL_TRACE(true); END;
  
     Para configurar o identificar de cliente (que pode ser o nome da conta de um pool de conexões), execute o comando abaixo substituindo o valor da string:
     SQL> BEGIN DBMS_SESSION.SET_IDENTIFIER('FABIO'); END;
   
     Para desabilitar a geração de trace extendido, execute o comando abaixo:
     SQL> BEGIN DBMS_SESSION.SET_SQL_TRACE(false); END;
          5- Package DBMS_SYSTEM
          Esta package foi introduzida provavelmente no Oracle 8i e é similar à DBMS_SESSION. Difere-se apenas pela possibilidade de poder afetar qualquer sessão do BD, e não somente a sessão atual ou aquelas que tiveram um identificador de cliente previamente configuradas.
   
     Para habilitar a geração de trace na sessão de outro usuário, siga o exemplo abaixo substituindo os valores dos parâmetros:
     SQL> BEGIN 
                  DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(sid => 15, serial# => 2388, true);
                END;
   
     Para desabilitar a geração de trace na sessão do mesmo usuário, execute:
     SQL> BEGIN 
                  DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION(sid => 15, serial# => 2388, false);
                END;
          6- Package DBMS_MONITOR
          A package DBMS_MONITOR foi criada no Oracle Database 10G e é uma evolução da packages DBMS_SYSTEM. Ela contém todas as funcionalidades da package anterior e permite, por exemplo, habilitar trace no nível de serviço, módulo ou ação. Essa é a package atualmente recomendada pela Oracle para gerenciar trace e deve ser utilizada em conjunto com as packages DBMS_SESSION ou DBMS_APPLICATION_INFO para gerenciar traces em diversos níveis (não somente usuários individuais).
    
     Para habilitar a geração de trace na sessão de outro usuário, siga o exemplo abaixo substituindo os valores das variáveis:
     SQL> BEGIN 
                  DBMS_MONITOR.SESSION_TRACE_ENABLE(session_id => 15, serial_num => 2388, waits => true, binds => true);
                END;
    
        Para desabilitar a geração de trace na sessão do mesmo usuário, execute:
     SQL> BEGIN 
                  DBMS_MONITOR.SESSION_TRACE_DISABLE(sid => 15serial_num => 2388);
                END;

   
      Existe ainda o AUTOTRACE, que pode ser utilizado no SQL Plus ou ferramentas similares, e que permite ver estatísticas da instrução SQL sem gerar arquivo externo, porém com poucas e limitadas informações. É importante entender que em um arquivo de SQL Trace você não encontrará o tempo de execução de blocos PL/SQL, mas somente as instruções SQL executadas dentro destes blocos (ou fora deles). Se você precisa analisar o desempenho de blocos PL/SQL, consulte a package DBMS_TRACE.

     Para descobrir onde trace está habilitado, conecte-se no BD com privilégios administrativos e consulte a visão DBA_ENABLED_TRACES
 Dando continuidade ao artigo Analisando traces em Bancos de Dados Oracle - Parte 1, explicarei  hoje como analisar um arquivo trace, gerando-o através do 6º método (package DBMS_MONITOR) apresentado no artigo anterior. Começaremos gerando o trace de uma instrução SQL, e faremos em seguida, uma análise dos pontos principais que demonstram como ela foi executada e o seu desempenho.

     A instrução SQL que iremos executar, irá consultar dados de 2 tabelas do schema HR, obtendo as seguintes informações de empregados: Identificador, nome completoidentificador do departamento e o salário de cada empregado do departamento 10. Antes de executá-la, iremos habilitar trace na sessão do usuário HR, e após executá-la, iremos desabilitar o trace e iniciar a sua análise. Analisar um arquivo trace em seu formato original não é uma tarefa fácil, pois os dados não são gravados em um formato "amigável" (fácil de ler e entender). Para analisá-lo, iremos antes, convertê-lo em um formato amigável, utilizando o famoso utilitário tkprof. Existe outra ferramenta chamada Trace Analyzer, que oferece mais recursos que o tkprof, mas que depende de instalação adicional, motivo pelo qual eu não irei demonstrá-la neste artigo.
     Segue abaixo um roteiro para implementar o que está descrito acima:
 

1- GERANDO UM ARQUIVO DE SQL TRACE

Importante: Todos os passos deste roteiro deverão ser executados no SQL Plus, SQL Developer ou ferramenta similar, conectado com o usuário HR.

Passo 1: Habilitando trace na sessão de usuário:
     Para habilitar trace na sessão do usuário HR (usuário que executará a instrução SQL), iremos utilizar a package DBMS_MONITOR, porque o seu uso faz parte do método atualmente recomendado pela Oracle para tal finalidade (gerenciar sql trace):

    a) Configure um identificador de nome do arquivo trace (sufixo do nome do arquivo):
     SQL> alter session set tracefile_identifier='hr';

    b) Habilite trace na sessão do usuário (conectado como HR):
     SQL> EXEC DBMS_MONITOR.SESSION_TRACE_ENABLE(waits=>true, binds=>true);
  
Obs.: Para executar o comando acima, atribua privilégios de execute na package DBMS_MONITOR para o usuário HR (grant execute on dbms_monitor to hr;). Se você é um DBA e precisa habilitar trace na sessão do usuário HR, identifique-o na visão V$SESSION (select sid, serial# from v$session where username = 'HR') e forneça o valor correspondente das colunas sid e serial# para o comando a seguir: EXEC DBMS_MONITOR.SESSION_TRACE_ENABLE(session_id => 15serial_num => 2388, waits => true, binds => true);

Passo 2: Executando a instrução SQL:
    Execute a instrução SQL abaixo 11 vezes para que sejam registradas no arquivo trace as suas estatísticas de execução:
  SQL> SELECT   employee_id,       
                first_name||' '||last_name as complete_name,       
                DEPARTMENT_ID,
                SALARY
       FROM     HR.EMPLOYEES E
       WHERE    DEPARTMENT_ID =20
       ORDER BY SALARY DESC;

Passo 3: Desabilitando trace:
   Agora que já terminamos de executar a instrução SQL, podemos desabilitar a geração de trace executando o comando abaixo:
     SQL> EXEC DBMS_MONITOR.SESSION_TRACE_DISABLE;

Obs.: Se você é um DBA e precisa desabilitar trace na sessão do usuário HR, identifique-o na visão V$SESSION (select sid, serial# from v$session where username = 'HR') e forneça o valor correspondente das colunas sid serial# para o comando a seguir: EXEC DBMS_MONITOR.SESSION_TRACE_DISABLE(session_id => 15serial_num => 2388);

 
2 - UTILIZANDO O TKPROF

Passo 1: Utilizando o tkprof para gerar um trace "amigável":
     Neste passo precisamos converter o arquivo trace em outro arquivo que contenha os dados em um formato amigável, que a gente consiga ler e interpretar os seus dados.
  
    a) Para descobrir o local onde o arquivo trace foi gerado, execute o comando abaixo, conectado no BD com um usuário que tenha privilégios administrativos e anote o valor do retorno da coluna VALUE. É importante ressaltar que o caminho resultante irá variar, de acordo com a estrutura de pastas em que o software do Oracle Database foi instalado:
     SQL> show parameter background_dump_dest
  
Resultado:
NAME                                    TYPE         VALUE      
-------------------------------- ----------- -----------------------------------------------------------------------------------
background_dump_dest         string        /home/oracle/app/oracle/diag/rdbms/orcl/orcl/trace

    b) Abra uma janela de prompt de comandos do Sistema Operacional e entre na pasta resultante do passo anterior, como no exemplo abaixo (ver Imagem 01):
     $ cd /home/oracle/app/oracle/diag/rdbms/orcl/orcl/trace         

    c) Localize o arquivo trace que você gerou, pesquisando pelo identificador que foi atribuído no passo a) do roteiro GERANDO UM ARQUIVO DE SQL TRACE, como no exemplo abaixo:
     $ ll *hr* 

    d) Utilize o tkprof para converter o arquivo com a extensão .trc, localizado no passo anterior, em outro arquivo com o nome result.txt, como no exemplo abaixo:
     $ tkprof orcl_ora_3803_hr.trc result.txt sys=no
  
Obs.: O tkprof está sendo executado com 3 parâmetros: nome do arquivo trace, nome do arquivo de saída e um valor para o parâmetro sys. Somente o nome do arquivo trace é um parâmetro obrigatório. O valor no foi fornecido para o parâmetro sys para evitar que sql recursivo seja incluso no arquivo result.txtO tkprof aceita vários outros parâmetros. Para ver uma lista completa destes parâmetros e os valores possíveis, digite apenas tkprof no prompt de comandos.


Imagem 01 - Utilizando o tkprof
  
3- ANALISANDO O ARQUIVO TRACE

     Chegamos no roteiro final. Agora iremos analisar o arquivo de sql trace "amigável" gerado com o nome result.txt no roteiro anterior. Como o seu conteúdo é grande, extraí dele somente a parte que nos interessa (aquela que contém as estatísticas de execução da instrução SQL). As informações que iremos analisar estão destacadas em vermelho na Listagem 01 e subdivididas em seções, com nomes indicados em azul para facilitar referências nas explicações. Ressalto novamente que não entrarei em todos os detalhes sobre o assunto, comentarei apenas os pontos principais:
   
********************************************************************************
SELECT        employee_id,
                      first_name||' '||last_name as complete_name,
                      DEPARTMENT_ID,
                      SALARY
FROM          HR.EMPLOYEES E
WHERE        DEPARTMENT_ID =20
ORDER BY   SALARY DESC


call         count     cpu    elapsed  disk      query   current  rows                                        ***  Seção 1 ***
----------- --------  -------- ------------ -------- ---------- ----------  ----------

Parse       11         0.02       0.02          0             0            0                0

Execute   11         0.00       0.00          0             0            0                0

Fetch       11         0.00       0.01          2           22            0              22

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

total         33         0.02       0.03          2           22            0              22



Misses in library cache during parse: 1

Optimizer mode: FIRST_ROWS                                                                                          ***  Seção 2 ***

Parsing user id: 2821

Number of plan statistics captured: 2



Rows (1st) Rows (avg) Rows (max)  Row Source Operation                                         ***  Seção 3 ***


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

         2             2                    2                SORT ORDER BY (cr=2 pr=1 pw=0 time=5728 us cost=9 size=52 card=2)
         2             2                    2                TABLE ACCESS BY INDEX ROWID EMPLOYEES 
                                                                           (cr=2 pr=1 pw=0 time=5703 us cost=8 size=52 card=2)
         2             2                    2                INDEX RANGE SCAN EMP_DEPARTMENT_IX 
                                                                           (cr=1 pr=0 pw=0 time=2740 us cost=4 size=0 card=2)(object id 84939)

Elapsed times include waiting on following events:                                                       ***  Seção 4 ***
Event waited on                             Times     Max. Wait    Total Waited
  ----------------------------------------   Waited  ---------------  ------------------
  SQL*Net message to client           11           0.00               0.00
  db file sequential read                      2           0.00               0.01
  SQL*Net message from client       11           0.00               0.02
********************************************************************************

Listagem 01: Informações de estatísticas de SQL Trace
      


     Analisando a Seção 1, podemos verificar que a instrução SQL foi executada 11 vezes e que ela gastou mais tempo na fase de Parse (0.02 de 0.03) do que nas outras fases. Isso normalmente ocorre em instruções SQL que atualizam e/ou acessam e retornam poucos dados. Em instruções com longo processamento ou que atualizam, ou retornam e consultam muitos dados, o ideal é que o tempo de Parse seja muito menor que o tempo de Execute Fetch. O mais importante é que nesta seção a gente consegue ver estes tempos de forma isolada, ou seja,  por fase. 

     Seguem abaixo as informações de cada coluna apresentada na Seção 1:
          - call: Nome da fase de execução da instrução SQL;
          - count: Quantidade de vezes em que a instrução passou por uma determinada fase;
          - cpu: Tempo total de cpu dedicado à instrução SQL. 
          - elapsed disk: Tempo total de execução dedicado à instrução SQL. Inclui tempo de execução e tempo e espera;
          - disk: Quantidade total de blocos lidos/escritos em disco;
          - query: Quantidade total de blocos lidos em memória (leitura consistente);
          - current: Quantidade total de blocos lidos em memória (dados atuais, lidos normalmente em UPDATEs);
          - rows: Quantidade total de linhas processadas.
        
     Analisando a Seção 2, podemos verificar que a instrução SQL foi executada com o parâmetro OPTIMIZER_MODE configurado como FIRST_ROWS. O valor FIRST_ROWS normalmente força o uso de índices, que podem ser utilizados pela instrução SQL. Essa informação é muito importante para sabermos o porquê de um índice ser utilizado ou não, pois com o valor padrão (ALL_ROWS), existem muitas variantes do sistema que podem influenciar no comportamento do otimizador e fazer com que ele ignore índices e realize um Full Table Scan.

     Na Seção 3, a gente vê detalhes sobre o plano de execução da instrução SQL. Aqui estão as informações mais importantes do trace, onde podemos ver o tempo de execução por operação da instrução SQL. A análise minuciosa desta seção é muito importante para o trabalho de tuning, pois nela podemos identificar a(s) operação(ões) mais cara(s) da execução de uma instrução SQL, para posteriormente concentrar nossos esforços de otimização somente nesta(s) operação(ões), pois elas são as que causam maior impacto na instrução SQL e onde normalmente podemos ter mais sucesso no trabalho de tuning. Analisando esta seção, descobri que a operação mais cara foi aquela necessária para realizar a ordenação pela coluna SALARY, ou seja, a operação SORT ORDER BY, encontrada na primeira linha de informações da seção (SORT ORDER BY (cr=2 pr=1 pw=0 time=5728 us cost=9 size=52 card=2)). Esta operação tem custo 9 e tempo de execução estimado igual à 0.005728s, enquanto que, as demais (TABLE ACCESS... e INDEX RANGE SCAN...) tem custo 8 e 4, e tempo de execução estimado igual à 0.005703s e 0.00247s,  respectivamente. As informações que podemos analisar sobre cada operação aparecem entre parenteses, após o nome delas. São elas:
          - cr (consistent reads): Qtde. de blocos lidos em memória de forma consistente;
          - pr (physical reads): Qtde. de blocos lidos em disco;
          - pw (physical writes): Qtde. de blocos escritos em disco;
          - time (elapsed time): Tempo total gasto em microsegundos pela operação.
          - cost (optimizer cost): Custo da operação.
          - size (estimated size): Tamanho estimado em bytes dos dados processados.
          - card (estimated cardinality): Qtde. estimada de linhas processadas.
     Na Seção 4, encontram-se as informações sobre estatísticas de eventos de espera (wait events). O tempo de execução de uma instrução SQL é igual ao tempo de cpu + tempo de espera. Uma instrução SQL eficiente normalmente tem um baixo tempo de espera, em relação ao tempo de CPU, portanto, quando você identificar que o tempo de um determinado evento de espera está muito alto, investigue o porquê disso estar acontecendo. É importante entender, também, que nem todo evento de espera trata-se de um problema

CONCLUSÃO
     Após analisar todas as seções do sql trace, pode-se concluir que a instrução SQL foi executada de forma eficiente, pois ela teve um tempo total de execução baixo (0.03s ou 0.002s por execução), usou um índice para filtrar os dados do departamento, e fez o acesso aos dados de forma eficiente!
 
                                                  Resumo comandos:

/**************************/ setup TKPROF/ **************************
 1 - checar se há trace habilitado

    select * from sys.wri$_tracing_enabled;
ou
     SELECT *FROM DBA_ENABLED_TRACES;

2 - verificar o caminho de gravação:
   
    SHOW PARAMETER USER_DUMP_DEST;

3 - Identificar a sessão do usuário:

select sid, serial#, username from v$session;

SID     SERIAL#  USERNAME
        ------    ------- 
        136       7854  SCOTT
   


4 - alterar a nivel de sessão

    alter session set user_dump_dest="c:\nome_do_diretorio";

    alter session set tracefile_identifier ="nome_do_trace";


5 - nomear o trace para identificação

    alter session set tracefile_identifier ='Nome_do_trace';
como exemplo:
    alter session set tracefile_identifier ='Nome_do_user_data_TK';


6 - habilitar a estatística da sessão:

    alter session set timed_statistics=true;
7 - ativar o trace da sessão

    EXECUTE DBMS_MONITOR.SESSION_TRACE_ENABLE;


De posse do SID (Session ID) e o serial# da sessão,  habilitar o trace:

exec DBMS_MONITOR.session_trace_enable (session_id => 136,serial_num => 7854); -- 136 é o SID e 7854 é o SERIAL# da sessão auditada

ou pelo cliente:

exec dbms_monitor.client_id_trace_enable (client_id=>'nome_cliente');


/************************** /DISABLE TKPROF/ **************************


1 - desabilitar o trace

    exec DBMS_MONITOR.session_trace_disable (session_id => 136,serial_num => 7854); -- 136 é o SID e 7854 é o SERIAL# da sessão auditada

ou 
    exec dbms_monitor.client_id_trace_disable (client_id=>'nome_cliente');


2 - para gerar o TKPROF:

tkprof /caminho/nome_do_arquivo /caminho/nome_do_arquivo_de_saida_trace.txt

TKPRO - SQL TRACE 1

 DBMS_MONITOR – SQL TRACE
Fontes :
http://felipe.fortaltec.com.br/blog/?p=28
https://sites.google.com/site/telodba/blog/tkprof

O Pacote DBMS_MONITOR nos auxilia através do SQL Trace gerando dados e estatísticas de uma determinada sessão. Estas informações são geradas para cada instrução DML executada dentro da sessão auditada.
Dentre as informações geradas, podemos citar:

* CPU: Tempo de CPU e Average;
* Tempo Decorrido: Tempo gasto com a execução da instrução SQL;
* I/O: Número de leituras físicas de blocos no disco;
* Consultas: Número de buffers obtidos na leitura;
* Processamento: Quantidade de linhas processadas em cada chamada;
* Contadores PFE: Parse, Fetch, Execute;

Todas estas informações ficam armazenadas em um diretório (USER_DUMP_DEST) através de um arquivo de trace (TRC).

- TKPROF

Como dito anteriormente, todos os arquivos de trace são armazenados em uma pasta do sistema operacional (USER_DUMP_DEST) em um arquivo de extensão trc. Este arquivo por si só não possui as informações que queremos (instruções executadas, tempo decorrido, quantidade de execuções, etc…). Para transformarmos este arquivo trc em um arquivo de texto legível, utilizamos o TKPROF. Em termos gerais, este utilitário quem vem dentro da pasta de binários do Oracle é o responsável por transformar o arquivo de trace em um arquivo de texto compreensível.

Exemplo de utilização:
$> TKPROF /pasta_user_dump_dest/arquivo.trc /pasta_destino/arquivo.txt

OBS: checar se há traces habilitados na view  DBA_ENABLED_TRACES que é baseada na tabela underlying data dictionary  SYS.WRI$_TRACING_ENABLED




select * from sys.wri$_tracing_enabled; 

ou  SELECT *FROM DBA_ENABLED_TRACES;
 

 - HABILITANDO O TRACE NA SESSÃO

Normalmente, os arquivos de trace são gerados em diretórios específicos do oracle. Neste caso, o trace sempre ficará armazenado em um diretório chamado USER_DUMP_DEST.
Para verificar o destino deste diretório basta executar no SQL o seguinte comando:

SHOW PARAMETER USER_DUMP_DEST
   
* Caso precise alterar o destino deste diretório, execute o seguinte comando:
ALTER SYSTEM SET USER_DUMP_DEST = 'caminho/da/nova/pasta';

ou alterar somente o destino da sessão:

(WINDOWS)

alter session set user_dump_dest="c:\nome_do_diretorio";
 
alter session set 
tracefile_identifier ="nome_do_trace"; 
   
* Quando alterar a pasta se certifique que o usuário oracle tenha permissão de leitura/escrita nela.

Bem, inicialmente você precisará saber qual sessão auditar. Neste caso, iremos realizar uma consulta na visão do dicionário de dados chamada V$SESSION (Nesta visão, podemos ter um apanhado geral sobre todas as sessões que estão abertas no banco).
Filtrar  pelo usuário do banco (Username), Usuário do S.O. (OSUSER), Máquina (MACHINE) ou Programa (PROGRAM):

alter session set nls_date_format='dd/mm/yyyy hh24:mi';
set linesize 2000
set pagesize 1000

SELECT * from v$session where program <> 'plsqldev.exe'
ou para identificar, usar a V$SESSION

select sid, serial#, username 
from v$session;
 
   SID     SERIAL#  USERNAME
     ------    -------  ------------
       133       4152  SYS
       136       7854  SCOTT
       139         53  KIMBERLY
       140        561  DBSNMP
       141          4  DBSNMP
 
   
Agora de posse do SID (Session ID) e o serial# da sessão,  habilitar o trace:

exec DBMS_MONITOR.session_trace_enable (session_id => 136,serial_num => 7854); -- 136 é o SID e 7854 é o SERIAL# da sessão auditada

Habilitando o trace pelo cliente:

SQL> exec dbms_monitor.client_id_trace_enable
(client_id=>'nome_cliente');


Trace se encontra habilitado e tudo que for feito nesta sessão será escrito no arquivo trc.
Aguardar o usuário fazer todos os SELECTS, UPDATES, DELETES…

- DESABILITANDO O TRACE E GERANDO ARQUIVO DE RESULTADOS

Após realizar todas as operações de DML,  executar o seguinte script para desativar o trace:

exec DBMS_MONITOR.session_trace_disable (session_id => 136,serial_num => 7854); -- 136 é o SID e 7854 é o SERIAL# da sessão auditada
   
Após executar o comando acima, o arquivo TRC será gerado na pasta USER_DUMP_DEST.
A única coisa que você deve fazer agora é utilizar o TKPROF para gerar o arquivo de resultados (txt). O comando TKPROF possui diversos parâmetros para formatar a saída do Trace, mas simplesmente informando o arquivo de trace e um arquivo de saída já são suficientes para vermos os recursos disponibilizados pelo comando:

$> tkprof /app/oracle/admin/udump/msid_146632.trc /home/oracle/saida_trace.txt


Pronto! Basta agora obter o arquivo gerado (txt) e analisar os resultados!

Segue abaixo uma visão geral de tudo que devemos fazer (passo a passo):
PgSQL
-- Ver sessões abertas (Filtrar de acordo com necessidade) 
select * from v$session where program <> 'plsqldev.exe' and username = 'GESTOR_MASTER' 

-- Para ativar o Trace (Especificar SID e SERIAL#)
 exec DBMS_MONITOR.session_trace_enable (session_id => 136,serial_num => 7854);

-- Após operações de DML, será necessário desativar o trace. --
Para desativar o Trace (Especificar SID e SERIAL#)
exec DBMS_MONITOR.session_trace_disable (session_id => 136,serial_num => 7854); 

 -- Para ver onde o arquivo de trace (TRC) será armazenado:
SHOW PARAMETER USER_DUMP_DEST; --

Para gerar o arquivo de texto contendo as operações auditadas -- Executar no SHELL: --
tkprof /caminho/arquivo.trc /caminho/arquivo_destino.txt


TKPROF

posted Oct 27, 2010, 9:09 AM by Telo Vieira   [ updated Oct 29, 2010, 4:44 AM ]
É uma ferramenta que converte os arquivos de trace do Oracle num formato de leitura mais compreensível.
O parâmetro TIMED_STATISTICS deve ser configurado para TRUE.
Não vou entrar em detalhes sobre como gerar o TKPROF, mas sim, como interpretar seu resultado. Mesmo assim uma pequena parte dele, pois o assunto é extenso.
O resultado do TKPROF contém algumas informações de performance consolidadas para todos os SQLs analisados.
Vou destacar as descritas abaixo:
********************************************************************************
count    = número de vezes que o SQL foi executado
cpu      = tempo de CPU utilizado em segundos
elapsed  = tempo decorrido (elapsed time) em segundos. Inclui CPU Time + Wait Time
disk     = número de data blocks(1) físicos lidos do disco (datafiles)
query    = número de buffers(2) (blocks) CR recuperados (Consistent Read). Usualmente são recuperados em queries
current  = número de buffers (blocks) CURRENT recuperados (Current Mode). Geralmente para updates,inserts e deletes
rows     = número de linhas (rows) processadas pelo fetch ou execute call
********************************************************************************
Veja um exemplo:
select a.owner,b.object_name,b.status from dba_tables a, dba_objects b
where a.owner='SYSTEM' and
a.table_name = b.object_name and a.owner = b.owner
call count cpu elapsed disk query current rows
Parse 1 1.45 1.68 0 6 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.22 0.26 1 1868 0 191
total 4 1.67 1.95 1 1874 0 191

Aproveito para explicar o que é PARSE, EXECUTE e FETCH, visto que essa pergunta já me foi feita algumas vezes.
PARSE    : Verifica a sintaxe do SQL, segurança/existência dos objetos envolvidos e o  traduz para um plano de execução;
EXECUTE  : A real execução do SQL pelo Oracle. Modifica dos dados para INSERT, DELETE E UPDATE. Identifica as linhas (rows) selecionadas pelo SELECT;
FETCH    : Recupera as linhas (rows) retornadas pela query. É utilizado somente para SELECTS; Observamos, no exemplo acima, que para um determinado SQL:
a) Feito o PARSE 1 vez com tempo de duração de 1.68 segundos (CPU time + 0.23 segundos);
b) Foi executado 1 vez com tempo de CPU de 0,00 segundos e elapsed time de 0.00 segundos;
c) As 191 linhas foram recuperadas em  0.26 segundos (CPU time + 0.04 segundos);
d) Foram lidos 1 buffer físico do disco, 1868 CR e 0 CURRENTs
e) #blocks in the table: #blocks = query mode / # of times the query was executed
f) Cada chamada do fetch recuperou aproximadamente 95 linhas (rows/count);
g) Um fetch no database realiza no mínimo um LIO (Logical I/O) para fazer o PIN do Oracle block no database buffer cache;

(1) data block é a menor unidade de dados usada pelo oracle database (DB_BLOCK_SIZE)
(2) buffer é onde os blocos são colocados após a leitura deles no disco.

Prática:

Parte 1




 Parte 2


Documentação oficial:
http://docs.oracle.com/cd/B19306_01/server.102/b14211/sqltrace.htm#i4640

restore total de banco