Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Estatísticas dinâmicas adaptáveis ​​matam o desempenho em 12.1.0.2 RAC


Após uma atualização recente para 12.1.0.2, tenho trabalhado em vários problemas de desempenho. Muitos desses problemas estão relacionados a um SQL ruim e vários problemas que resolvi e provei que eram problemas na versão 11.2.0.4 antiga. Isso significa apenas que sempre foi um problema. Mas as pessoas estão aproveitando a oportunidade da atualização para me fazer consertar coisas que estão quebradas há um bom tempo.

Ao analisar os problemas de desempenho, encontrei duas instruções SQL que estão se tornando porcos em nosso sistema. Aqui está uma captura de tela das duas instruções SQL como vistas no Lighty:











Podemos ver que a primeira instrução SQL (SQL ID 4b4wp0a8dvkf0) está consumindo CPU e aguardando leituras do arquivo de controle. A segunda instrução SQL (SQL ID frjd8zfy2jfdq) está usando muita CPU e também possui vários outros eventos de espera. Aqui está o texto SQL dessas instruções.

Código SQL:frjd8zfy2jfdq
SELECT
    executions
    ,end_of_fetch_count
    ,elapsed_time / px_servers elapsed_time
    ,cpu_time / px_servers cpu_time
    ,buffer_gets / executions buffer_gets
  FROM
    (
      SELECT
          SUM (executions) AS executions
          ,SUM (
            CASE
              WHEN px_servers_executions > 0
              THEN px_servers_executions
              ELSE executions
            END
          ) AS px_servers
          ,SUM (end_of_fetch_count) AS end_of_fetch_count
          ,SUM (elapsed_time) AS elapsed_time
          ,SUM (cpu_time) AS cpu_time
          ,SUM (buffer_gets) AS buffer_gets
        FROM
          gv$sql
        WHERE
          executions > 0
          AND sql_id = : 1
          AND parsing_schema_name = : 2



Código SQL:4b4wp0a8dvkf0
SELECT
    executions
    ,end_of_fetch_count
    ,elapsed_time / px_servers elapsed_time
    ,cpu_time / px_servers cpu_time
    ,buffer_gets / executions buffer_gets
  FROM
    (
      SELECT
          SUM (executions_delta) AS EXECUTIONS
          ,SUM (
            CASE
              WHEN px_servers_execs_delta > 0
              THEN px_servers_execs_delta
              ELSE executions_delta
            END
          ) AS px_servers
          ,SUM (end_of_fetch_count_delta) AS end_of_fetch_count
          ,SUM (elapsed_time_delta) AS ELAPSED_TIME
          ,SUM (cpu_time_delta) AS CPU_TIME
          ,SUM (buffer_gets_delta) AS BUFFER_GETS
        FROM
          DBA_HIST_SQLSTAT s
          ,V$DATABASE d
          ,DBA_HIST_SNAPSHOT sn
        WHERE
          s.dbid = d.dbid
          AND bitand (
            nvl (
              s.flag
              ,0
            )
            ,1
          ) = 0
          AND sn.end_interval_time > (
            SELECT
                systimestamp AT TIME ZONE dbtimezone
              FROM
                dual
          ) - 7
          AND s.sql_id = : 1
          AND s.snap_id = sn.snap_id
          AND s.instance_number = sn.instance_number
          AND s.dbid = sn.dbid
          AND parsing_schema_name = : 2
    )
 
    )
 
Ambos fazem parte dos novos recursos Adaptive Query Optimization agora na versão 12c. Mais especificamente, eles estão relacionados à parte de Estatísticas Dinâmicas Automáticas desse recurso. SQL ID frjd8zfy2jfdq é o Oracle obtendo informações sobre o desempenho da instrução SQL do GV$SQL. SQL ID 4b4wp0a8dvkf0 é o Oracle obtendo as mesmas informações sobre o desempenho da instrução SQL das tabelas do Active Session History.

Bertand Drouvot discute isso em seu blog aqui:https://bdrouvot.wordpress.com/2014/10/17/watch-out-for-optimizer_adaptive_features-as-it-may-have-a-huge-negative-impact/

Além disso, participei de uma sessão de Christian Antognini no Oak Table World 2015, onde ele mencionou essas instruções SQL. Seus slides da OTW são praticamente os mesmos que estes:

http://www.soug.ch/fileadmin/user_upload/SIGs/SIG_150521_Tuning_R/Christian_Antognini_AdaptiveDynamicSampling_trivadis.pdf

Esses links acima e as Notas MOS que eu mencionei abaixo forneceram muito da base das informações que apresento aqui.

Todos os recursos de Otimização de Consulta Adaptativa devem melhorar a vida do DBA. Eles devem ajudar o Optimizer a tomar melhores decisões, mesmo depois que uma instrução SQL começou a ser executada. Nesse caso específico, essas consultas devem ajudar o CBO a obter melhores estatísticas, mesmo que as estatísticas estejam ausentes. Isso pode ajudar a melhorar o desempenho do SQL, mas, como descobri no meu caso, está prejudicando o desempenho geral do sistema.

Para obter mais informações sobre otimização de consulta adaptável, consulte a Nota 2031605.1. Isso o levará a outras notas, mas em particular a esta discussão, Nota 2002108.1 Estatísticas dinâmicas automáticas.

Para piorar a situação, meu sistema de produção vendo esse comportamento é o Oracle RAC. Quando o SQL ID frjd8zfy2jfdq é executado em sistemas Oracle RAC, a consulta paralela é usada, o que é óbvio na minha captura de tela pelo enq:PS – contenção e eventos de espera “PX%”.

Podemos transformar a amostragem dinâmica da seguinte forma:

alter system set optimizer_dynamic_sampling=0 escopo=ambos;

O valor padrão deste parâmetro é 2.

Para mim, essas consultas estão consumindo recursos e impactando o desempenho geral do banco de dados. No entanto, esses recursos são projetados para melhorar atuação. Sempre existe o risco de que, se eu desativar o recurso para ajudar no desempenho em uma área, isso prejudique o desempenho em outra área. Mas como o Optimizer_dynamic_sampling<>11 para mim, não estou usando esse recurso ao máximo, então não estou obtendo todo o benefício que poderia ser. Além disso, nosso código não depende da amostragem dinâmica para ocorrer. Então é seguro para mim desligar isso.

Depois de alterar o parâmetro, pude ver uma alteração imediata, conforme mostrado abaixo.









A linha vermelha indica a hora em que fiz a alteração. É claro que a versão ASH desta consulta não está mais em execução. A versão V$SQL ainda está em execução, mas não vê mais eventos de espera de consulta paralela. É principalmente apenas consumindo CPU agora. Considero este progresso, mas não uma resolução completa.

Como observação lateral, eu poderia ter desativado todos os recursos de otimização de consulta adaptável com o seguinte:
alter system set optimizer_adaptive_features=false scope=both;

Mas eu sei que tenho consultas “desfrutando” da Otimização de Junção Adaptativa e não quero desligar tudo, apenas amostragem dinâmica.

Então agora o que fazer com o SQL ID frjd8zfy2jfdq? Vamos ver se podemos resolver o problema restante. De uma das notas MOS que vinculei acima, sei que podemos definir este parâmetro oculto:
alter system set "_optimizer_dsdir_usage_control"=0 scope=both;

O valor padrão para este parâmetro oculto era 126 no meu sistema 12.1.0.2. Encontrei a configuração padrão com o seguinte:
select a.ksppinm name, b.ksppstvl value, b.ksppstdf deflt,
from
  sys.x$ksppi a,
  sys.x$ksppcv b
where  a.indx = b.indx
  and  a.ksppinm like '\_%' escape '\'
  and  a.ksppinm like '%dsdir%'
order by name;



Esse valor é importante caso eu queira defini-lo de volta sem precisar tirar o parâmetro do SPFILE, o que exigiria tempo de inatividade.

Agora posso continuar alterando esse parâmetro oculto e definindo-o como zero. Aqui está como essa instrução SQL fica no Lighty após a alteração:









Parece ser “missão cumprida” ao interromper a execução dessas duas instruções SQL.

Aqueles que executam a versão 12.1.0.2 no Oracle RAC podem querer verificar se essas duas instruções SQL não estão causando problemas de desempenho por conta própria.

Este parece ser um daqueles casos em que um recurso que deveria ajudar o desempenho na verdade faz o oposto.