sql >> Base de Datos >  >> RDS >> Oracle

Las estadísticas dinámicas adaptativas matan el rendimiento en 12.1.0.2 RAC

Después de una actualización reciente a 12.1.0.2, he estado trabajando en varios problemas de rendimiento. Muchos de estos problemas están relacionados con un SQL deficiente y una serie de problemas que he resuelto y he demostrado que eran problemas en la versión anterior 11.2.0.4. Esto solo significa que siempre ha sido un problema. Pero la gente está aprovechando la oportunidad de la actualización para que arregle las cosas que han estado rotas durante bastante tiempo.

Mientras observaba los problemas de rendimiento, me encontré con dos declaraciones SQL que se están convirtiendo en cerdos en nuestro sistema. Aquí hay una captura de pantalla de las dos declaraciones SQL como se ve en Lighty:

Podemos ver que la primera instrucción SQL (SQL ID 4b4wp0a8dvkf0) consume CPU y espera lecturas del archivo de control. La segunda instrucción SQL (ID de SQL frjd8zfy2jfdq) usa mucha CPU y también tiene otros eventos de espera. Aquí está el texto SQL de estas declaraciones.

ID de 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 de 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 son parte de las nuevas funciones de optimización de consultas adaptativas ahora en 12c. Más específicamente, se relacionan con la parte Estadísticas dinámicas automáticas de esta característica. SQL ID frjd8zfy2jfdq es Oracle que obtiene información sobre el rendimiento de las sentencias SQL de GV$SQL. SQL ID 4b4wp0a8dvkf0 es Oracle que obtiene la misma información sobre el rendimiento de las sentencias SQL de las tablas del historial de sesiones activas.

Bertand Drouvot analiza esto en su blog aquí:https://bdrouvot.wordpress.com/2014/10/17/watch-out-for-optimizer_adaptive_features-as-it-may-have-a-huge-negative-impact/

Además, asistí a una sesión de Christian Antognini en Oak Table World 2015 donde mencionó estas declaraciones SQL. Sus diapositivas de OTW son más o menos iguales a estas:

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

Esos enlaces anteriores y las Notas de MOS a las que hago referencia a continuación proporcionaron gran parte de la base de la información que presento aquí.

Se supone que todas las características de Adaptive Query Optimization mejorarán la vida del DBA. Se supone que ayudan al Optimizador a tomar mejores decisiones, incluso después de que se haya iniciado la ejecución de una instrucción SQL. En este caso específico, se supone que estas consultas ayudan a la CBO a obtener mejores estadísticas, incluso si faltan las estadísticas. Esto puede ayudar a mejorar el rendimiento de SQL, pero como descubrí en mi caso, está obstaculizando el rendimiento general del sistema.

Para obtener más información sobre Adaptive Query Optimization, consulte la nota 2031605.1. Esto lo llevará a otras notas, pero en particular a esta discusión, Nota 2002108.1 Estadísticas dinámicas automáticas.

Para empeorar las cosas, mi sistema de producción que ve este comportamiento es Oracle RAC. Cuando se realiza el ID de SQL frjd8zfy2jfdq en los sistemas Oracle RAC, se utiliza una consulta paralela, lo cual es obvio en mi captura de pantalla con enq:PS:contención y eventos de espera "PX%".

Podemos desactivar el muestreo dinámico de la siguiente manera:

alterar el conjunto del sistema Optimizer_dynamic_sampling=0 alcance=ambos;

El valor predeterminado de este parámetro es 2.

Para mí, estas consultas consumen recursos y afectan el rendimiento general de la base de datos. Sin embargo, estas funciones están diseñadas para mejorar actuación. Siempre existe el riesgo de que si desactivo la función para mejorar el rendimiento en un área, perjudique el rendimiento en otra área. Pero desde Optimizer_dynamic_sampling<>11 para mí, no estoy usando esa función al máximo, por lo que no obtengo todo el beneficio que podría obtener. Además, nuestro código no depende de que se produzca un muestreo dinámico. Así que es seguro para mí apagar esto.

Después de cambiar el parámetro, pude ver un cambio inmediato como se muestra a continuación.

La línea roja indica la hora en que realicé el cambio. Está claro que la versión ASH de esta consulta ya no se está ejecutando. La versión de V$SQL todavía se está ejecutando, pero ya no ve eventos de espera de consultas paralelas. En su mayoría, solo consume CPU ahora. Considero este progreso, pero no una resolución completa.

Como nota al margen, podría haber desactivado todas las funciones de Adaptive Query Optimization con lo siguiente:

alter system set optimizer_adaptive_features=false scope=both;

Pero sí sé que tengo consultas que "disfrutan" de la Optimización de unión adaptable y no quiero apagarlo todo, solo el muestreo dinámico.

Entonces, ¿qué hacer ahora con el ID de SQL frjd8zfy2jfdq? Veamos si podemos resolver el problema restante. De una de las notas de MOS que vinculé anteriormente, sé que podemos establecer este parámetro oculto:

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

El valor predeterminado para este parámetro oculto era 126 en mi sistema 12.1.0.2. Encontré la configuración predeterminada con lo siguiente:

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;

Este valor es importante en caso de que quiera restablecerlo sin tener que sacar el parámetro del SPFILE, lo que requeriría tiempo de inactividad.

Ahora puedo proceder a cambiar este parámetro oculto y configurarlo en cero. Así es como se ve esa declaración SQL en Lighty después del cambio:

Parece ser una "misión cumplida" al detener la ejecución de esas dos declaraciones SQL.

Aquellos que ejecutan 12.1.0.2 en Oracle RAC pueden querer verificar que estas dos declaraciones SQL no están causando problemas de rendimiento por sí mismas.

Este parece ser uno de esos casos en los que una función que se supone que ayuda al rendimiento en realidad hace lo contrario.