Oracle
 sql >> Database >  >> RDS >> Oracle

Le statistiche dinamiche adattive uccidono le prestazioni in 12.1.0.2 RAC

Dopo un recente aggiornamento alla 12.1.0.2, ho lavorato su una serie di problemi di prestazioni. Molti di questi problemi sono correlati a un SQL scadente e una serie di problemi che ho risolto ho dimostrato erano problemi nella vecchia versione 11.2.0.4. Questo significa solo che è sempre stato un problema. Ma le persone stanno sfruttando l'opportunità dell'aggiornamento per farmi riparare cose che sono state interrotte per un po' di tempo.

Mentre esaminavo i problemi di prestazioni, mi sono imbattuto in due istruzioni SQL che stanno diventando maiali nel nostro sistema. Ecco uno screenshot delle due istruzioni SQL viste in Lighty:

Possiamo vedere che la prima istruzione SQL (SQL ID 4b4wp0a8dvkf0) sta consumando CPU e attende le letture dal file di controllo. La seconda istruzione SQL (ID SQL frjd8zfy2jfdq) utilizza molta CPU e ha anche una serie di altri eventi di attesa. Ecco il testo SQL di queste istruzioni.

ID 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

ID 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
    )
 
    )
 

Entrambi fanno parte delle nuove funzionalità di ottimizzazione adattiva delle query ora in 12c. Più specificamente, si riferiscono alla parte Statistiche dinamiche automatiche di questa funzionalità. L'ID SQL frjd8zfy2jfdq è Oracle che ottiene informazioni sulle prestazioni dell'istruzione SQL da GV$SQL. L'ID SQL 4b4wp0a8dvkf0 è Oracle che ottiene le stesse informazioni sulle prestazioni dell'istruzione SQL dalle tabelle della cronologia delle sessioni attive.

Bertand Drouvot ne discute sul suo blog qui:https://bdrouvot.wordpress.com/2014/10/17/watch-out-for-optimizer_adaptive_features-as-it-may-have-a-huge-negative-impact/

Inoltre, ho partecipato a una sessione di Christian Antognini all'Oak Table World 2015 in cui ha menzionato queste istruzioni SQL. Le sue diapositive di OTW sono più o meno le stesse di queste:

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

Quei collegamenti sopra e le note MOS a cui faccio riferimento di seguito hanno fornito gran parte delle informazioni che presento qui.

Tutte le funzionalità di ottimizzazione delle query adattive dovrebbero migliorare la vita del DBA. Dovrebbero aiutare l'ottimizzatore a prendere decisioni migliori, anche dopo che un'istruzione SQL ha iniziato l'esecuzione. In questo caso specifico, queste query dovrebbero aiutare il CBO a ottenere statistiche migliori, anche se mancano le statistiche. Questo può aiutare a migliorare le prestazioni SQL, ma come ho riscontrato nel mio caso, sta ostacolando le prestazioni complessive del sistema.

Per ulteriori informazioni sull'ottimizzazione adattiva delle query, vedere la nota 2031605.1. Questo ti porterà ad altre note, ma in particolare a questa discussione, Nota 2002108.1 Statistica dinamica automatica.

A peggiorare le cose è che il mio sistema di produzione che vede questo comportamento è Oracle RAC. Quando l'ID SQL frjd8zfy2jfdq viene eseguito su sistemi Oracle RAC, viene utilizzata una query parallela che è evidente dalla mia schermata di enq:PS – contesa e eventi di attesa "PX%".

Possiamo attivare il campionamento dinamico come segue:

altera il set di sistema optimization_dynamic_sampling=0 scope=both;

Il valore predefinito di questo parametro è 2.

Per me, queste query stanno consumando risorse e influiscono sulle prestazioni complessive del database. Tuttavia, queste funzionalità sono progettate per migliorare prestazione. C'è sempre il rischio che se disattivo la funzione per migliorare le prestazioni in un'area, si riducano le prestazioni in un'altra area. Ma dal momento che optimizationr_dynamic_sampling<>11 per me, non sto utilizzando questa funzionalità al massimo, quindi non sto ottenendo tutti i vantaggi che potrei avere. Inoltre, il nostro codice non si basa sul campionamento dinamico. Quindi è sicuro per me disattivarlo.

Dopo aver modificato il parametro, ho potuto vedere una modifica immediata come mostrato di seguito.

La linea rossa indica l'ora in cui ho apportato la modifica. È chiaro che la versione ASH di questa query non è più in esecuzione. La versione V$SQL è ancora in esecuzione ma non vede più eventi di attesa di query parallele. Per lo più ora consuma solo CPU. Considero questo progresso, ma non una risoluzione completa.

Come nota a margine, avrei potuto disattivare tutte le funzionalità di ottimizzazione adattiva delle query con quanto segue:

alter system set optimizer_adaptive_features=false scope=both;

Ma so che ho domande che "godono" dell'ottimizzazione adattiva dei join e non voglio disattivare tutto, solo campionamento dinamico.

Quindi ora cosa fare con l'ID SQL frjd8zfy2jfdq? Vediamo se riusciamo a risolvere il problema rimanente. Da una delle note MOS che ho collegato sopra, so che possiamo impostare questo parametro nascosto:

alter system set "_optimizer_dsdir_usage_control"=0 scope=both;

Il valore predefinito per questo parametro nascosto era 126 nel mio sistema 12.1.0.2. Ho trovato l'impostazione predefinita con quanto segue:

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;

Questo valore è importante nel caso in cui volessi reimpostarlo senza dover rimuovere il parametro da SPFILE, il che richiederebbe tempi di inattività.

Ora posso procedere con la modifica di questo parametro nascosto e impostandolo su zero. Ecco come appare l'istruzione SQL in Lighty dopo la modifica:

Sembra essere "missione compiuta" nell'interrompere l'esecuzione di queste due istruzioni SQL.

Coloro che eseguono 12.1.0.2 su Oracle RAC potrebbero voler verificare che queste due istruzioni SQL non causino problemi di prestazioni di per sé.

Questo sembra essere uno di quei casi in cui una funzionalità che dovrebbe aiutare le prestazioni in realtà fa il contrario.